@remotion/vercel 4.0.467 → 4.0.469

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.
@@ -167,8 +167,8 @@ function checkValidInputRange(arr) {
167
167
  }
168
168
  }
169
169
  function checkInfiniteRange(name, arr) {
170
- if (arr.length < 2) {
171
- throw new Error(name + " must have at least 2 elements");
170
+ if (arr.length < 1) {
171
+ throw new Error(name + " must have at least 1 element");
172
172
  }
173
173
  for (const element of arr) {
174
174
  if (typeof element !== "number") {
@@ -235,6 +235,9 @@ function interpolate(input, inputRange, outputRange, options) {
235
235
  if (typeof input !== "number") {
236
236
  throw new TypeError("Cannot interpolate an input which is not a number");
237
237
  }
238
+ if (inputRange.length === 1) {
239
+ return outputRange[0];
240
+ }
238
241
  const range = findRange(input, inputRange);
239
242
  return interpolateFunction(input, [inputRange[range], inputRange[range + 1]], [outputRange[range], outputRange[range + 1]], {
240
243
  easing: resolveEasingForSegment(range),
@@ -1140,8 +1143,10 @@ try {
1140
1143
 
1141
1144
  // script-embed:render-video-script
1142
1145
  var script2 = `// src/scripts/render-video.ts
1143
- import { statSync } from "fs";
1146
+ import { randomUUID } from "crypto";
1147
+ import { stat, readFile, rename, writeFile } from "fs/promises";
1144
1148
  import { RenderInternals } from "@remotion/renderer";
1149
+ import { put } from "@vercel/blob";
1145
1150
 
1146
1151
  // ../core/dist/esm/no-react.mjs
1147
1152
  function interpolateFunction(input, inputRange, outputRange, options) {
@@ -1196,8 +1201,8 @@ function checkValidInputRange(arr) {
1196
1201
  }
1197
1202
  }
1198
1203
  function checkInfiniteRange(name, arr) {
1199
- if (arr.length < 2) {
1200
- throw new Error(name + " must have at least 2 elements");
1204
+ if (arr.length < 1) {
1205
+ throw new Error(name + " must have at least 1 element");
1201
1206
  }
1202
1207
  for (const element of arr) {
1203
1208
  if (typeof element !== "number") {
@@ -1264,6 +1269,9 @@ function interpolate(input, inputRange, outputRange, options) {
1264
1269
  if (typeof input !== "number") {
1265
1270
  throw new TypeError("Cannot interpolate an input which is not a number");
1266
1271
  }
1272
+ if (inputRange.length === 1) {
1273
+ return outputRange[0];
1274
+ }
1267
1275
  const range = findRange(input, inputRange);
1268
1276
  return interpolateFunction(input, [inputRange[range], inputRange[range + 1]], [outputRange[range], outputRange[range + 1]], {
1269
1277
  easing: resolveEasingForSegment(range),
@@ -2064,17 +2072,58 @@ var NoReactInternals = {
2064
2072
  };
2065
2073
 
2066
2074
  // src/scripts/render-video.ts
2075
+ var PROGRESS_FILE = "/vercel/sandbox/progress.json";
2067
2076
  var config = JSON.parse(process.argv[2]);
2068
2077
  var noop = () => {
2069
2078
  return;
2070
2079
  };
2080
+ var progressWrite = Promise.resolve();
2081
+ function getExtension(filePath) {
2082
+ const lastDot = filePath.lastIndexOf(".");
2083
+ if (lastDot === -1) {
2084
+ return "";
2085
+ }
2086
+ return filePath.slice(lastDot);
2087
+ }
2088
+ var writeProgress = (message) => {
2089
+ const tmpFile = \`\${PROGRESS_FILE}.tmp\`;
2090
+ progressWrite = progressWrite.then(async () => {
2091
+ await writeFile(tmpFile, JSON.stringify(message));
2092
+ await rename(tmpFile, PROGRESS_FILE);
2093
+ });
2094
+ return progressWrite;
2095
+ };
2096
+ var reportProgress = async (message) => {
2097
+ console.log(JSON.stringify(message));
2098
+ await writeProgress(message);
2099
+ };
2100
+ var uploadToVercelBlob = async ({
2101
+ sandboxFilePath,
2102
+ contentType,
2103
+ access,
2104
+ blobPath
2105
+ }) => {
2106
+ const blobToken = process.env.BLOB_READ_WRITE_TOKEN;
2107
+ if (!blobToken) {
2108
+ throw new Error("BLOB_READ_WRITE_TOKEN is not set.");
2109
+ }
2110
+ const actualBlobPath = blobPath ?? \`renders/\${randomUUID()}\${getExtension(sandboxFilePath)}\`;
2111
+ const fileBuffer = await readFile(sandboxFilePath);
2112
+ const { size } = await stat(sandboxFilePath);
2113
+ const blob = await put(actualBlobPath, fileBuffer, {
2114
+ access,
2115
+ contentType,
2116
+ token: blobToken
2117
+ });
2118
+ return { url: blob.downloadUrl, size };
2119
+ };
2071
2120
  try {
2072
2121
  const serializedInputProps = NoReactInternals.serializeJSONWithSpecialTypes({
2073
2122
  data: config.inputProps,
2074
2123
  indent: undefined,
2075
2124
  staticBase: null
2076
2125
  }).serializedString;
2077
- console.log(JSON.stringify({ stage: "opening-browser", overallProgress: 0 }));
2126
+ await reportProgress({ stage: "opening-browser", overallProgress: 0 });
2078
2127
  const browser = await RenderInternals.internalOpenBrowser({
2079
2128
  browser: "chrome",
2080
2129
  browserExecutable: config.browserExecutable,
@@ -2089,7 +2138,7 @@ try {
2089
2138
  }),
2090
2139
  chromeMode: config.chromeMode
2091
2140
  });
2092
- console.log(JSON.stringify({ stage: "selecting-composition", overallProgress: 0.02 }));
2141
+ await reportProgress({ stage: "selecting-composition", overallProgress: 0.02 });
2093
2142
  const { metadata: composition } = await RenderInternals.internalSelectComposition({
2094
2143
  serializedInputPropsWithCustomSchema: serializedInputProps,
2095
2144
  envVariables: config.envVariables,
@@ -2169,7 +2218,7 @@ try {
2169
2218
  sampleRate: config.sampleRate,
2170
2219
  puppeteerInstance: browser,
2171
2220
  onProgress: (progress) => {
2172
- console.log(JSON.stringify({
2221
+ reportProgress({
2173
2222
  stage: "render-progress",
2174
2223
  progress: {
2175
2224
  renderedFrames: progress.renderedFrames,
@@ -2180,8 +2229,10 @@ try {
2180
2229
  progress: progress.progress,
2181
2230
  stitchStage: progress.stitchStage
2182
2231
  },
2183
- overallProgress: 0.04 + progress.progress * 0.96
2184
- }));
2232
+ overallProgress: 0.04 + progress.progress * 0.94
2233
+ }).catch((error) => {
2234
+ console.error(error.message);
2235
+ });
2185
2236
  },
2186
2237
  onDownload: () => {
2187
2238
  return;
@@ -2203,12 +2254,44 @@ try {
2203
2254
  onProgress: noop
2204
2255
  })
2205
2256
  });
2206
- console.log(JSON.stringify({ stage: "render-complete", overallProgress: 1 }));
2257
+ await progressWrite;
2258
+ console.log(JSON.stringify({ stage: "render-complete", overallProgress: 0.98 }));
2207
2259
  await browser.close({ silent: false });
2208
- const { size } = statSync(config.outputLocation ?? "/tmp/video.mp4");
2209
- console.log(JSON.stringify({ stage: "done", size, contentType, overallProgress: 1 }));
2260
+ const sandboxFilePath = config.outputLocation ?? "/tmp/video.mp4";
2261
+ if (config.vercelBlob) {
2262
+ await reportProgress({ stage: "uploading", overallProgress: 0.99 });
2263
+ const { url, size } = await uploadToVercelBlob({
2264
+ sandboxFilePath,
2265
+ contentType,
2266
+ access: config.vercelBlob.access,
2267
+ blobPath: config.vercelBlob.blobPath
2268
+ });
2269
+ await reportProgress({
2270
+ stage: "done",
2271
+ url,
2272
+ size,
2273
+ contentType,
2274
+ overallProgress: 1
2275
+ });
2276
+ } else {
2277
+ const { size } = await stat(sandboxFilePath);
2278
+ await reportProgress({
2279
+ stage: "done",
2280
+ size,
2281
+ contentType,
2282
+ overallProgress: 1
2283
+ });
2284
+ }
2210
2285
  } catch (err) {
2211
- console.error(err.message);
2286
+ const message = err.message;
2287
+ await writeProgress({
2288
+ stage: "error",
2289
+ message,
2290
+ overallProgress: 1
2291
+ }).catch(() => {
2292
+ return;
2293
+ });
2294
+ console.error(message);
2212
2295
  process.exit(1);
2213
2296
  }
2214
2297
  `;
@@ -2501,50 +2584,135 @@ async function createSandbox({
2501
2584
  await report(1, "Sandbox ready");
2502
2585
  return sandbox;
2503
2586
  }
2504
- // src/render-media-on-vercel.ts
2505
- async function renderMediaOnVercel({
2506
- sandbox,
2507
- compositionId,
2508
- inputProps,
2509
- onProgress,
2510
- outputFile = "/tmp/video.mp4",
2511
- codec = "h264",
2512
- crf,
2513
- imageFormat,
2514
- pixelFormat,
2515
- envVariables = {},
2516
- frameRange,
2517
- everyNthFrame = 1,
2518
- proResProfile,
2519
- chromiumOptions = {},
2520
- scale = 1,
2521
- preferLossless = false,
2522
- enforceAudioTrack = false,
2523
- disallowParallelEncoding = false,
2524
- concurrency,
2525
- metadata,
2526
- licenseKey,
2527
- videoBitrate,
2528
- audioBitrate,
2529
- encodingMaxRate,
2530
- encodingBufferSize,
2531
- muted = false,
2532
- numberOfGifLoops,
2533
- x264Preset,
2534
- gopSize,
2535
- colorSpace = "default",
2536
- jpegQuality = 80,
2537
- audioCodec,
2538
- logLevel = "info",
2539
- timeoutInMilliseconds = 30000,
2540
- forSeamlessAacConcatenation = false,
2541
- separateAudioTo,
2542
- hardwareAcceleration = "disable",
2543
- offthreadVideoCacheSizeInBytes,
2544
- mediaCacheSizeInBytes,
2545
- offthreadVideoThreads,
2546
- sampleRate
2587
+ // src/get-render-progress.ts
2588
+ import { Sandbox as Sandbox2 } from "@vercel/sandbox";
2589
+ var PROGRESS_FILE = "/vercel/sandbox/progress.json";
2590
+ var isStoppedOrExpiredSandboxError = (error) => {
2591
+ if (typeof error === "object" && error !== null && "code" in error) {
2592
+ return error.code === "sandbox_stopped";
2593
+ }
2594
+ if (!(error instanceof Error)) {
2595
+ return false;
2596
+ }
2597
+ return error.message.includes("sandbox_stopped") || error.message.includes("Sandbox has stopped execution") || error.message.includes("no longer available");
2598
+ };
2599
+ var getCommandError = async (command) => {
2600
+ const stderr = await command.stderr().catch(() => "");
2601
+ const stdout = await command.stdout().catch(() => "");
2602
+ const output = [stderr, stdout].filter(Boolean).join(" ");
2603
+ return output || `Render command exited with code ${command.exitCode}.`;
2604
+ };
2605
+ async function getRenderProgress({
2606
+ sandboxId,
2607
+ cmdId
2547
2608
  }) {
2609
+ let sandbox;
2610
+ try {
2611
+ sandbox = await Sandbox2.get({ sandboxId });
2612
+ } catch {
2613
+ return { stage: "expired" };
2614
+ }
2615
+ let command;
2616
+ try {
2617
+ command = await sandbox.getCommand(cmdId);
2618
+ } catch (err) {
2619
+ if (isStoppedOrExpiredSandboxError(err)) {
2620
+ return { stage: "expired" };
2621
+ }
2622
+ return {
2623
+ stage: "error",
2624
+ message: err.message,
2625
+ overallProgress: 1
2626
+ };
2627
+ }
2628
+ let buffer;
2629
+ try {
2630
+ buffer = await sandbox.readFileToBuffer({ path: PROGRESS_FILE });
2631
+ } catch (err) {
2632
+ if (isStoppedOrExpiredSandboxError(err)) {
2633
+ return { stage: "expired" };
2634
+ }
2635
+ return {
2636
+ stage: "error",
2637
+ message: err.message,
2638
+ overallProgress: 1
2639
+ };
2640
+ }
2641
+ if (!buffer) {
2642
+ if (command.exitCode === null) {
2643
+ return { stage: "starting", overallProgress: 0 };
2644
+ }
2645
+ const message = await getCommandError(command);
2646
+ return { stage: "error", message, overallProgress: 1 };
2647
+ }
2648
+ let progress;
2649
+ try {
2650
+ progress = JSON.parse(buffer.toString("utf-8"));
2651
+ } catch {
2652
+ return {
2653
+ stage: "error",
2654
+ message: "Could not parse the render progress file.",
2655
+ overallProgress: 1
2656
+ };
2657
+ }
2658
+ if (command.exitCode !== null && command.exitCode !== 0) {
2659
+ const message = await getCommandError(command);
2660
+ return { stage: "error", message, overallProgress: 1 };
2661
+ }
2662
+ return progress;
2663
+ }
2664
+ // src/render-media-on-vercel.ts
2665
+ var DEFAULT_DETACHED_SANDBOX_TIMEOUT = 30 * 60 * 1000;
2666
+ var internalRenderMediaOnVercel = async (options) => {
2667
+ const {
2668
+ sandbox,
2669
+ compositionId,
2670
+ inputProps,
2671
+ onProgress,
2672
+ outputFile = "/tmp/video.mp4",
2673
+ codec = "h264",
2674
+ crf,
2675
+ imageFormat,
2676
+ pixelFormat,
2677
+ envVariables = {},
2678
+ frameRange,
2679
+ everyNthFrame = 1,
2680
+ proResProfile,
2681
+ chromiumOptions = {},
2682
+ scale = 1,
2683
+ preferLossless = false,
2684
+ enforceAudioTrack = false,
2685
+ disallowParallelEncoding = false,
2686
+ concurrency,
2687
+ metadata,
2688
+ licenseKey,
2689
+ videoBitrate,
2690
+ audioBitrate,
2691
+ encodingMaxRate,
2692
+ encodingBufferSize,
2693
+ muted = false,
2694
+ numberOfGifLoops,
2695
+ x264Preset,
2696
+ gopSize,
2697
+ colorSpace = "default",
2698
+ jpegQuality = 80,
2699
+ audioCodec,
2700
+ logLevel = "info",
2701
+ timeoutInMilliseconds = 30000,
2702
+ forSeamlessAacConcatenation = false,
2703
+ separateAudioTo,
2704
+ hardwareAcceleration = "disable",
2705
+ offthreadVideoCacheSizeInBytes,
2706
+ mediaCacheSizeInBytes,
2707
+ offthreadVideoThreads,
2708
+ sampleRate,
2709
+ detached = false,
2710
+ detachedSandboxTimeoutInMilliseconds = DEFAULT_DETACHED_SANDBOX_TIMEOUT
2711
+ } = options;
2712
+ const vercelBlob = options.detached ? options.vercelBlob : undefined;
2713
+ if (detached && !vercelBlob) {
2714
+ throw new Error("The vercelBlob option is required when detached is set to true.");
2715
+ }
2548
2716
  const serveUrl = `/vercel/sandbox/${REMOTION_SANDBOX_BUNDLE_DIR}`;
2549
2717
  const renderConfig = {
2550
2718
  serveUrl,
@@ -2590,13 +2758,26 @@ async function renderMediaOnVercel({
2590
2758
  browserExecutable: null,
2591
2759
  binariesDirectory: null,
2592
2760
  repro: false,
2593
- sampleRate: sampleRate ?? 48000
2761
+ sampleRate: sampleRate ?? 48000,
2762
+ vercelBlob: vercelBlob ? {
2763
+ blobPath: vercelBlob.blobPath ?? null,
2764
+ access: vercelBlob.access
2765
+ } : null
2594
2766
  };
2595
2767
  const renderCmd = await sandbox.runCommand({
2596
2768
  cmd: "node",
2597
2769
  args: ["render-video.mjs", JSON.stringify(renderConfig)],
2598
- detached: true
2770
+ detached: true,
2771
+ env: vercelBlob ? { BLOB_READ_WRITE_TOKEN: vercelBlob.blobToken } : undefined
2599
2772
  });
2773
+ if (detached) {
2774
+ await sandbox.extendTimeout(detachedSandboxTimeoutInMilliseconds);
2775
+ return {
2776
+ sandboxId: sandbox.sandboxId,
2777
+ cmdId: renderCmd.cmdId,
2778
+ outputFile
2779
+ };
2780
+ }
2600
2781
  let contentType = "application/octet-stream";
2601
2782
  for await (const log of renderCmd.logs()) {
2602
2783
  if (log.stream === "stdout") {
@@ -2617,7 +2798,8 @@ async function renderMediaOnVercel({
2617
2798
  throw new Error(`Render failed: ${stderr} ${stdout}`);
2618
2799
  }
2619
2800
  return { sandboxFilePath: outputFile, contentType };
2620
- }
2801
+ };
2802
+ var renderMediaOnVercel = internalRenderMediaOnVercel;
2621
2803
  // src/render-still-on-vercel.ts
2622
2804
  async function renderStillOnVercel({
2623
2805
  sandbox,
@@ -2749,6 +2931,7 @@ export {
2749
2931
  uploadToVercelBlob,
2750
2932
  renderStillOnVercel,
2751
2933
  renderMediaOnVercel,
2934
+ getRenderProgress,
2752
2935
  createSandbox,
2753
2936
  addBundleToSandbox
2754
2937
  };
@@ -0,0 +1,5 @@
1
+ import type { RenderProgress } from './types';
2
+ export declare function getRenderProgress({ sandboxId, cmdId }: {
3
+ sandboxId: string;
4
+ cmdId: string;
5
+ }): Promise<RenderProgress>;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export { addBundleToSandbox } from './add-bundle-to-sandbox';
2
2
  export { createSandbox } from './create-sandbox';
3
+ export { getRenderProgress } from './get-render-progress';
3
4
  export { renderMediaOnVercel } from './render-media-on-vercel';
4
5
  export { renderStillOnVercel } from './render-still-on-vercel';
5
- export type { AudioCodec, Bitrate, ChromeMode, ChromiumOptions, Codec, ColorSpace, CreateSandboxOnProgress, FrameRange, HardwareAccelerationOption, LogLevel, OpenGlRenderer, PixelFormat, ProResProfile, RenderMediaOnProgress, RenderMediaOnVercelProgress, RenderMediaProgress, RenderStillOnVercelProgress, StillImageFormat, StitchingState, VercelBlobAccess, VercelSandbox, VideoImageFormat, X264Preset, } from './types';
6
+ export type { AudioCodec, Bitrate, ChromeMode, ChromiumOptions, Codec, ColorSpace, CreateSandboxOnProgress, FrameRange, HardwareAccelerationOption, LogLevel, OpenGlRenderer, PixelFormat, ProResProfile, RenderMediaOnProgress, RenderMediaOnVercelProgress, RenderMediaProgress, RenderProgress, RenderStillOnVercelProgress, StillImageFormat, StitchingState, VercelBlobAccess, VercelBlobUploadOptions, VercelSandbox, VideoImageFormat, X264Preset, } from './types';
6
7
  export { uploadToVercelBlob } from './upload-to-vercel-blob';
@@ -1,6 +1,6 @@
1
1
  import type { Sandbox } from '@vercel/sandbox';
2
- import type { AudioCodec, Bitrate, ChromiumOptions, Codec, ColorSpace, FrameRange, HardwareAccelerationOption, LogLevel, PixelFormat, ProResProfile, RenderMediaOnVercelProgress, VideoImageFormat, X264Preset } from './types';
3
- export declare function renderMediaOnVercel({ sandbox, compositionId, inputProps, onProgress, outputFile, codec, crf, imageFormat, pixelFormat, envVariables, frameRange, everyNthFrame, proResProfile, chromiumOptions, scale, preferLossless, enforceAudioTrack, disallowParallelEncoding, concurrency, metadata, licenseKey, videoBitrate, audioBitrate, encodingMaxRate, encodingBufferSize, muted, numberOfGifLoops, x264Preset, gopSize, colorSpace, jpegQuality, audioCodec, logLevel, timeoutInMilliseconds, forSeamlessAacConcatenation, separateAudioTo, hardwareAcceleration, offthreadVideoCacheSizeInBytes, mediaCacheSizeInBytes, offthreadVideoThreads, sampleRate }: {
2
+ import type { AudioCodec, Bitrate, ChromiumOptions, Codec, ColorSpace, FrameRange, HardwareAccelerationOption, LogLevel, PixelFormat, ProResProfile, RenderMediaOnVercelProgress, VercelBlobUploadOptions, VideoImageFormat, X264Preset } from './types';
3
+ type RenderMediaOnVercelBaseOptions = {
4
4
  sandbox: Sandbox;
5
5
  compositionId: string;
6
6
  inputProps: Record<string, unknown>;
@@ -42,7 +42,25 @@ export declare function renderMediaOnVercel({ sandbox, compositionId, inputProps
42
42
  mediaCacheSizeInBytes?: number | null;
43
43
  offthreadVideoThreads?: number | null;
44
44
  sampleRate?: number;
45
- }): Promise<{
46
- sandboxFilePath: string;
47
- contentType: string;
48
- }>;
45
+ detachedSandboxTimeoutInMilliseconds?: number;
46
+ };
47
+ type RenderMediaOnVercelRegularOptions = RenderMediaOnVercelBaseOptions & {
48
+ detached?: false;
49
+ };
50
+ type RenderMediaOnVercelDetachedOptions = RenderMediaOnVercelBaseOptions & {
51
+ detached: true;
52
+ vercelBlob: VercelBlobUploadOptions;
53
+ };
54
+ type RenderMediaOnVercelFunction = {
55
+ (options: RenderMediaOnVercelDetachedOptions): Promise<{
56
+ sandboxId: string;
57
+ cmdId: string;
58
+ outputFile: string;
59
+ }>;
60
+ (options: RenderMediaOnVercelRegularOptions): Promise<{
61
+ sandboxFilePath: string;
62
+ contentType: string;
63
+ }>;
64
+ };
65
+ export declare const renderMediaOnVercel: RenderMediaOnVercelFunction;
66
+ export {};
package/dist/types.d.ts CHANGED
@@ -17,33 +17,55 @@ export type RenderMediaOnVercelProgress = {
17
17
  progress: RenderMediaProgress;
18
18
  overallProgress: number;
19
19
  };
20
- export type RenderStillOnVercelProgress = {
21
- stage: 'opening-browser';
20
+ export type RenderProgress = {
21
+ stage: 'starting';
22
+ overallProgress: number;
23
+ } | RenderMediaOnVercelProgress | {
24
+ stage: 'uploading';
22
25
  overallProgress: number;
23
26
  } | {
24
- stage: 'selecting-composition';
27
+ stage: 'done';
28
+ url: string;
29
+ size: number;
30
+ contentType: string;
25
31
  overallProgress: number;
32
+ } | {
33
+ stage: 'error';
34
+ message: string;
35
+ overallProgress: number;
36
+ } | {
37
+ stage: 'expired';
26
38
  };
27
- export type { HardwareAccelerationOption, ProResProfile, } from '@remotion/renderer/client';
28
- export type VercelBlobAccess = 'public' | 'private';
29
- export type SandboxRenderMediaMessage = {
39
+ export type RenderStillOnVercelProgress = {
30
40
  stage: 'opening-browser';
31
41
  overallProgress: number;
32
42
  } | {
33
43
  stage: 'selecting-composition';
34
44
  overallProgress: number;
35
- } | {
36
- stage: 'render-progress';
37
- progress: RenderMediaProgress;
45
+ };
46
+ export type { HardwareAccelerationOption, ProResProfile, } from '@remotion/renderer/client';
47
+ export type VercelBlobAccess = 'public' | 'private';
48
+ export type VercelBlobUploadOptions = {
49
+ blobToken: string;
50
+ access: VercelBlobAccess;
51
+ blobPath?: string;
52
+ };
53
+ export type SandboxRenderMediaMessage = RenderMediaOnVercelProgress | {
54
+ stage: 'render-complete';
38
55
  overallProgress: number;
39
56
  } | {
40
- stage: 'render-complete';
57
+ stage: 'uploading';
41
58
  overallProgress: number;
42
59
  } | {
43
60
  stage: 'done';
44
61
  size: number;
45
62
  contentType: string;
46
63
  overallProgress: number;
64
+ url?: string;
65
+ } | {
66
+ stage: 'error';
67
+ message: string;
68
+ overallProgress: number;
47
69
  };
48
70
  export type SandboxRenderStillMessage = {
49
71
  type: 'opening-browser';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remotion/vercel",
3
- "version": "4.0.467",
3
+ "version": "4.0.469",
4
4
  "description": "Render Remotion videos on Vercel Sandbox",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -23,8 +23,8 @@
23
23
  "url": "https://github.com/remotion-dev/remotion/issues"
24
24
  },
25
25
  "dependencies": {
26
- "@remotion/renderer": "4.0.467",
27
- "remotion": "4.0.467"
26
+ "@remotion/renderer": "4.0.469",
27
+ "remotion": "4.0.469"
28
28
  },
29
29
  "peerDependencies": {
30
30
  "@vercel/sandbox": ">=1.0.0"
@@ -38,7 +38,7 @@
38
38
  "./package.json": "./package.json"
39
39
  },
40
40
  "devDependencies": {
41
- "@remotion/eslint-config-internal": "4.0.467",
41
+ "@remotion/eslint-config-internal": "4.0.469",
42
42
  "@vercel/blob": "2.3.0",
43
43
  "@vercel/sandbox": "1.6.0",
44
44
  "eslint": "9.19.0",