@remotion/studio 4.0.365 → 4.0.367

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 (34) hide show
  1. package/dist/components/Modals.js +1 -1
  2. package/dist/components/RenderButton.js +3 -2
  3. package/dist/components/RenderModal/RenderModal.d.ts +7 -4
  4. package/dist/components/RenderModal/RenderModal.js +10 -4
  5. package/dist/components/RenderModal/RenderModalBasic.d.ts +4 -4
  6. package/dist/components/RenderQueue/actions.d.ts +3 -2
  7. package/dist/components/SidebarRenderButton.js +2 -1
  8. package/dist/components/Timeline/TimelineVideoInfo.js +12 -21
  9. package/dist/esm/chunk-5ywrk91r.js +59891 -0
  10. package/dist/esm/chunk-7e8m9pmd.js +59851 -0
  11. package/dist/esm/chunk-dve56fb5.js +42410 -0
  12. package/dist/esm/chunk-fsj6zw61.js +59894 -0
  13. package/dist/esm/chunk-j0sv4v53.js +59898 -0
  14. package/dist/esm/chunk-knnc4kgj.js +42408 -0
  15. package/dist/esm/chunk-q2rx70vn.js +60152 -0
  16. package/dist/esm/chunk-qvkzstcp.js +59855 -0
  17. package/dist/esm/chunk-rnxwsmc3.js +42417 -0
  18. package/dist/esm/chunk-xyx01n16.js +59894 -0
  19. package/dist/esm/chunk-y4fchsz3.js +59891 -0
  20. package/dist/esm/chunk-ycr2rhjx.js +42417 -0
  21. package/dist/esm/chunk-z4rfd84y.js +42410 -0
  22. package/dist/esm/internals.mjs +12064 -16831
  23. package/dist/esm/previewEntry.mjs +12064 -16831
  24. package/dist/esm/renderEntry.mjs +3 -2
  25. package/dist/helpers/extract-frames.d.ts +17 -0
  26. package/dist/helpers/extract-frames.js +62 -0
  27. package/dist/helpers/prores-labels.d.ts +2 -2
  28. package/dist/helpers/resize-video-frame.d.ts +4 -0
  29. package/dist/helpers/resize-video-frame.js +39 -0
  30. package/dist/helpers/retry-payload.js +8 -5
  31. package/dist/helpers/use-max-media-duration.js +14 -17
  32. package/dist/renderEntry.js +1 -0
  33. package/dist/state/modals.d.ts +7 -5
  34. package/package.json +10 -11
@@ -158,7 +158,8 @@ var renderContent = (Root) => {
158
158
  defaultCodec: bundleMode.compositionDefaultCodec,
159
159
  defaultOutName: bundleMode.compositionDefaultOutName,
160
160
  defaultVideoImageFormat: bundleMode.compositionDefaultVideoImageFormat,
161
- defaultPixelFormat: bundleMode.compositionDefaultPixelFormat
161
+ defaultPixelFormat: bundleMode.compositionDefaultPixelFormat,
162
+ defaultProResProfile: bundleMode.compositionDefaultProResProfile
162
163
  },
163
164
  children: [
164
165
  /* @__PURE__ */ jsx(Root, {}),
@@ -189,7 +190,7 @@ var renderContent = (Root) => {
189
190
  renderToDOM(/* @__PURE__ */ jsx("div", {
190
191
  children: /* @__PURE__ */ jsx(DelayedSpinner, {})
191
192
  }));
192
- import("./chunk-ha1wm1xf.js").then(({ StudioInternals }) => {
193
+ import("./chunk-ycr2rhjx.js").then(({ StudioInternals }) => {
193
194
  window.remotion_isStudio = true;
194
195
  window.remotion_isReadOnlyStudio = true;
195
196
  Internals.enableSequenceStackTraces();
@@ -0,0 +1,17 @@
1
+ type Options = {
2
+ track: {
3
+ width: number;
4
+ height: number;
5
+ };
6
+ container: string;
7
+ durationInSeconds: number | null;
8
+ };
9
+ export type ExtractFramesTimestampsInSecondsFn = (options: Options) => Promise<number[]> | number[];
10
+ export type ExtractFramesProps = {
11
+ src: string;
12
+ timestampsInSeconds: number[] | ExtractFramesTimestampsInSecondsFn;
13
+ onFrame: (frame: VideoFrame) => void;
14
+ signal?: AbortSignal;
15
+ };
16
+ export declare function extractFrames({ src, timestampsInSeconds, onFrame, signal, }: ExtractFramesProps): Promise<void>;
17
+ export {};
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractFrames = extractFrames;
4
+ const mediabunny_1 = require("mediabunny");
5
+ async function extractFrames({ src, timestampsInSeconds, onFrame, signal, }) {
6
+ const input = new mediabunny_1.Input({
7
+ formats: mediabunny_1.ALL_FORMATS,
8
+ source: new mediabunny_1.UrlSource(src),
9
+ });
10
+ const dispose = () => {
11
+ input.dispose();
12
+ };
13
+ if (signal) {
14
+ signal.addEventListener('abort', dispose, { once: true });
15
+ }
16
+ try {
17
+ const [durationInSeconds, format, videoTrack] = await Promise.all([
18
+ input.computeDuration(),
19
+ input.getFormat(),
20
+ input.getPrimaryVideoTrack(),
21
+ ]);
22
+ if (!videoTrack) {
23
+ throw new Error('No video track found in the input');
24
+ }
25
+ const timestamps = typeof timestampsInSeconds === 'function'
26
+ ? await timestampsInSeconds({
27
+ track: {
28
+ width: videoTrack.displayWidth,
29
+ height: videoTrack.displayHeight,
30
+ },
31
+ container: format.name,
32
+ durationInSeconds,
33
+ })
34
+ : timestampsInSeconds;
35
+ if (timestamps.length === 0) {
36
+ return;
37
+ }
38
+ const sink = new mediabunny_1.VideoSampleSink(videoTrack);
39
+ for await (const videoSample of sink.samplesAtTimestamps(timestamps)) {
40
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
41
+ break;
42
+ }
43
+ if (!videoSample) {
44
+ continue;
45
+ }
46
+ const videoFrame = videoSample.toVideoFrame();
47
+ onFrame(videoFrame);
48
+ }
49
+ }
50
+ catch (error) {
51
+ if (error instanceof mediabunny_1.InputDisposedError) {
52
+ return;
53
+ }
54
+ throw error;
55
+ }
56
+ finally {
57
+ dispose();
58
+ if (signal) {
59
+ signal.removeEventListener('abort', dispose);
60
+ }
61
+ }
62
+ }
@@ -1,2 +1,2 @@
1
- import type { ProResProfile } from '@remotion/renderer';
2
- export declare const labelProResProfile: (profile: ProResProfile) => "4444" | "4444 XQ (Best)" | "HQ" | "Proxy (Worst)" | "Light" | "Standard";
1
+ import type { _InternalTypes } from 'remotion';
2
+ export declare const labelProResProfile: (profile: _InternalTypes["ProResProfile"]) => "4444" | "4444 XQ (Best)" | "HQ" | "Proxy (Worst)" | "Light" | "Standard";
@@ -0,0 +1,4 @@
1
+ export declare const resizeVideoFrame: ({ frame, scale, }: {
2
+ frame: VideoFrame;
3
+ scale: number;
4
+ }) => VideoFrame;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resizeVideoFrame = void 0;
4
+ const calculateNewDimensionsFromScale = ({ width, height, scale, }) => {
5
+ const scaledWidth = Math.round(width * scale);
6
+ const scaledHeight = Math.round(height * scale);
7
+ return {
8
+ width: scaledWidth,
9
+ height: scaledHeight,
10
+ };
11
+ };
12
+ const resizeVideoFrame = ({ frame, scale, }) => {
13
+ var _a;
14
+ // No resize, no rotation
15
+ if (scale === 1) {
16
+ return frame;
17
+ }
18
+ const { width, height } = calculateNewDimensionsFromScale({
19
+ height: frame.displayHeight,
20
+ width: frame.displayWidth,
21
+ scale,
22
+ });
23
+ const canvas = new OffscreenCanvas(width, height);
24
+ const ctx = canvas.getContext('2d');
25
+ if (!ctx) {
26
+ throw new Error('Could not get 2d context');
27
+ }
28
+ canvas.width = width;
29
+ canvas.height = height;
30
+ ctx.scale(scale, scale);
31
+ ctx.drawImage(frame, 0, 0);
32
+ return new VideoFrame(canvas, {
33
+ displayHeight: height,
34
+ displayWidth: width,
35
+ duration: (_a = frame.duration) !== null && _a !== void 0 ? _a : undefined,
36
+ timestamp: frame.timestamp,
37
+ });
38
+ };
39
+ exports.resizeVideoFrame = resizeVideoFrame;
@@ -14,7 +14,7 @@ const makeRetryPayload = (job) => {
14
14
  compositionId: job.compositionId,
15
15
  initialFrame: job.frame,
16
16
  initialStillImageFormat: job.imageFormat,
17
- initialVideoImageFormat: defaults.videoImageFormat,
17
+ initialVideoImageFormat: null,
18
18
  initialJpegQuality: (_a = job.jpegQuality) !== null && _a !== void 0 ? _a : defaults.jpegQuality,
19
19
  initialScale: job.scale,
20
20
  initialLogLevel: job.logLevel,
@@ -23,7 +23,7 @@ const makeRetryPayload = (job) => {
23
23
  minConcurrency: defaults.minConcurrency,
24
24
  initialMuted: defaults.muted,
25
25
  initialEnforceAudioTrack: defaults.enforceAudioTrack,
26
- initialProResProfile: defaults.proResProfile,
26
+ initialProResProfile: null,
27
27
  initialx264Preset: defaults.x264Preset,
28
28
  initialPixelFormat: defaults.pixelFormat,
29
29
  initialAudioBitrate: defaults.audioBitrate,
@@ -56,6 +56,7 @@ const makeRetryPayload = (job) => {
56
56
  initialHardwareAcceleration: defaults.hardwareAcceleration,
57
57
  initialChromeMode: job.chromeMode,
58
58
  initialMediaCacheSizeInBytes: job.mediaCacheSizeInBytes,
59
+ renderDefaults: defaults,
59
60
  };
60
61
  }
61
62
  if (job.type === 'sequence') {
@@ -63,7 +64,7 @@ const makeRetryPayload = (job) => {
63
64
  type: 'render',
64
65
  initialFrame: 0,
65
66
  compositionId: job.compositionId,
66
- initialVideoImageFormat: defaults.videoImageFormat,
67
+ initialVideoImageFormat: null,
67
68
  initialJpegQuality: (_b = job.jpegQuality) !== null && _b !== void 0 ? _b : defaults.jpegQuality,
68
69
  initialScale: job.scale,
69
70
  initialLogLevel: job.logLevel,
@@ -72,7 +73,7 @@ const makeRetryPayload = (job) => {
72
73
  minConcurrency: defaults.minConcurrency,
73
74
  initialMuted: defaults.muted,
74
75
  initialEnforceAudioTrack: defaults.enforceAudioTrack,
75
- initialProResProfile: defaults.proResProfile,
76
+ initialProResProfile: null,
76
77
  initialx264Preset: defaults.x264Preset,
77
78
  initialPixelFormat: defaults.pixelFormat,
78
79
  initialAudioBitrate: defaults.audioBitrate,
@@ -106,6 +107,7 @@ const makeRetryPayload = (job) => {
106
107
  initialHardwareAcceleration: defaults.hardwareAcceleration,
107
108
  initialChromeMode: job.chromeMode,
108
109
  initialMediaCacheSizeInBytes: job.mediaCacheSizeInBytes,
110
+ renderDefaults: defaults,
109
111
  };
110
112
  }
111
113
  if (job.type === 'video') {
@@ -123,7 +125,7 @@ const makeRetryPayload = (job) => {
123
125
  minConcurrency: defaults.minConcurrency,
124
126
  initialMuted: job.muted,
125
127
  initialEnforceAudioTrack: job.enforceAudioTrack,
126
- initialProResProfile: (_d = job.proResProfile) !== null && _d !== void 0 ? _d : defaults.proResProfile,
128
+ initialProResProfile: (_d = job.proResProfile) !== null && _d !== void 0 ? _d : null,
127
129
  initialx264Preset: (_e = job.x264Preset) !== null && _e !== void 0 ? _e : defaults.x264Preset,
128
130
  initialPixelFormat: job.pixelFormat,
129
131
  initialAudioBitrate: job.audioBitrate,
@@ -156,6 +158,7 @@ const makeRetryPayload = (job) => {
156
158
  initialHardwareAcceleration: job.hardwareAcceleration,
157
159
  initialChromeMode: job.chromeMode,
158
160
  initialMediaCacheSizeInBytes: job.mediaCacheSizeInBytes,
161
+ renderDefaults: defaults,
159
162
  };
160
163
  }
161
164
  throw new Error(`Job ${JSON.stringify(job)} Not implemented`);
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useMaxMediaDuration = void 0;
4
- const media_parser_1 = require("@remotion/media-parser");
5
4
  const media_utils_1 = require("@remotion/media-utils");
5
+ const mediabunny_1 = require("mediabunny");
6
6
  const react_1 = require("react");
7
7
  const cache = new Map();
8
8
  const getSrc = (s) => {
@@ -22,18 +22,18 @@ const useMaxMediaDuration = (s, fps) => {
22
22
  if (!src) {
23
23
  return;
24
24
  }
25
- const controller = (0, media_parser_1.mediaParserController)();
26
- (0, media_parser_1.parseMedia)({
27
- src,
28
- controller,
29
- acknowledgeRemotionLicense: true,
30
- onDurationInSeconds: (duration) => {
31
- const durationOrInfinity = duration !== null && duration !== void 0 ? duration : Infinity;
32
- cache.set(src, Math.floor(durationOrInfinity * fps));
33
- setMaxMediaDuration(Math.floor(durationOrInfinity * fps));
34
- },
35
- }).catch((e) => {
36
- if ((0, media_parser_1.hasBeenAborted)(e)) {
25
+ const input = new mediabunny_1.Input({
26
+ formats: mediabunny_1.ALL_FORMATS,
27
+ source: new mediabunny_1.UrlSource(src),
28
+ });
29
+ input
30
+ .computeDuration()
31
+ .then((duration) => {
32
+ cache.set(src, Math.floor(duration * fps));
33
+ setMaxMediaDuration(Math.floor(duration * fps));
34
+ })
35
+ .catch((e) => {
36
+ if (e instanceof mediabunny_1.InputDisposedError) {
37
37
  return;
38
38
  }
39
39
  // In case of CORS errors, fall back to getVideoMetadata
@@ -49,10 +49,7 @@ const useMaxMediaDuration = (s, fps) => {
49
49
  });
50
50
  });
51
51
  return () => {
52
- try {
53
- controller.abort();
54
- }
55
- catch (_a) { }
52
+ input.dispose();
56
53
  };
57
54
  }, [src, fps]);
58
55
  return maxMediaDuration;
@@ -184,6 +184,7 @@ const renderContent = (Root) => {
184
184
  defaultOutName: bundleMode.compositionDefaultOutName,
185
185
  defaultVideoImageFormat: bundleMode.compositionDefaultVideoImageFormat,
186
186
  defaultPixelFormat: bundleMode.compositionDefaultPixelFormat,
187
+ defaultProResProfile: bundleMode.compositionDefaultProResProfile,
187
188
  }, children: [(0, jsx_runtime_1.jsx)(Root, {}), (0, jsx_runtime_1.jsx)(GetVideoComposition, { state: bundleMode })] }));
188
189
  renderToDOM(markup);
189
190
  }
@@ -1,7 +1,8 @@
1
- import type { AudioCodec, ChromeMode, Codec, ColorSpace, LogLevel, OpenGlRenderer, PixelFormat, ProResProfile, StillImageFormat, VideoImageFormat, X264Preset } from '@remotion/renderer';
1
+ import type { AudioCodec, ChromeMode, Codec, ColorSpace, LogLevel, OpenGlRenderer, PixelFormat, StillImageFormat, VideoImageFormat, X264Preset } from '@remotion/renderer';
2
2
  import type { HardwareAccelerationOption } from '@remotion/renderer/client';
3
- import type { PackageManager } from '@remotion/studio-shared';
3
+ import type { PackageManager, RenderDefaults } from '@remotion/studio-shared';
4
4
  import type React from 'react';
5
+ import type { _InternalTypes } from 'remotion';
5
6
  import type { CompType } from '../components/NewComposition/DuplicateComposition';
6
7
  import type { QuickSwitcherMode } from '../components/QuickSwitcher/NoResults';
7
8
  import type { RenderType } from '../components/RenderModal/RenderModalAdvanced';
@@ -11,16 +12,16 @@ export type RenderModalState = {
11
12
  compositionId: string;
12
13
  initialFrame: number;
13
14
  initialStillImageFormat: StillImageFormat;
14
- initialVideoImageFormat: VideoImageFormat;
15
+ initialVideoImageFormat: VideoImageFormat | null;
15
16
  initialJpegQuality: number;
16
17
  initialScale: number;
17
18
  initialLogLevel: LogLevel;
18
19
  initialConcurrency: number;
19
20
  initialMuted: boolean;
20
21
  initialEnforceAudioTrack: boolean;
21
- initialProResProfile: ProResProfile;
22
+ initialProResProfile: _InternalTypes['ProResProfile'] | null;
22
23
  initialx264Preset: X264Preset;
23
- initialPixelFormat: PixelFormat;
24
+ initialPixelFormat: PixelFormat | null;
24
25
  initialVideoBitrate: string | null;
25
26
  initialAudioBitrate: string | null;
26
27
  initialEveryNthFrame: number;
@@ -53,6 +54,7 @@ export type RenderModalState = {
53
54
  defaultConfigurationAudioCodec: AudioCodec | null;
54
55
  renderTypeOfLastRender: RenderType | null;
55
56
  defaulMetadata: Record<string, string> | null;
57
+ renderDefaults: RenderDefaults;
56
58
  };
57
59
  export type ModalState = {
58
60
  type: 'duplicate-comp';
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/studio"
4
4
  },
5
5
  "name": "@remotion/studio",
6
- "version": "4.0.365",
6
+ "version": "4.0.367",
7
7
  "description": "APIs for interacting with the Remotion Studio",
8
8
  "main": "dist",
9
9
  "sideEffects": false,
@@ -25,15 +25,14 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "semver": "7.5.3",
28
- "remotion": "4.0.365",
29
- "@remotion/player": "4.0.365",
30
- "@remotion/media-utils": "4.0.365",
31
- "@remotion/media-parser": "4.0.365",
32
- "@remotion/renderer": "4.0.365",
33
- "@remotion/web-renderer": "4.0.365",
34
- "@remotion/studio-shared": "4.0.365",
35
- "@remotion/webcodecs": "4.0.365",
36
- "@remotion/zod-types": "4.0.365",
28
+ "remotion": "4.0.367",
29
+ "@remotion/player": "4.0.367",
30
+ "@remotion/media-utils": "4.0.367",
31
+ "@remotion/renderer": "4.0.367",
32
+ "@remotion/web-renderer": "4.0.367",
33
+ "@remotion/studio-shared": "4.0.367",
34
+ "@remotion/zod-types": "4.0.367",
35
+ "mediabunny": "1.24.2",
37
36
  "memfs": "3.4.3",
38
37
  "source-map": "0.7.3",
39
38
  "open": "^8.4.2",
@@ -43,7 +42,7 @@
43
42
  "react": "19.0.0",
44
43
  "react-dom": "19.0.0",
45
44
  "@types/semver": "^7.3.4",
46
- "@remotion/eslint-config-internal": "4.0.365",
45
+ "@remotion/eslint-config-internal": "4.0.367",
47
46
  "eslint": "9.19.0"
48
47
  },
49
48
  "publishConfig": {