@remotion/vercel 4.0.468 → 4.0.470

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") {
@@ -196,6 +196,14 @@ function assertValidInterpolateEasingOption(easing, inputRangeLength) {
196
196
  }
197
197
  }
198
198
  }
199
+ function assertValidInterpolatePosterizeOption(posterize) {
200
+ if (posterize === undefined) {
201
+ return;
202
+ }
203
+ if (typeof posterize !== "number" || !Number.isFinite(posterize) || posterize <= 0) {
204
+ throw new Error(\`posterize must be a positive finite number, but got \${posterize}\`);
205
+ }
206
+ }
199
207
  function interpolate(input, inputRange, outputRange, options) {
200
208
  if (typeof input === "undefined") {
201
209
  throw new Error("input can not be undefined");
@@ -213,6 +221,7 @@ function interpolate(input, inputRange, outputRange, options) {
213
221
  checkInfiniteRange("outputRange", outputRange);
214
222
  checkValidInputRange(inputRange);
215
223
  assertValidInterpolateEasingOption(options?.easing, inputRange.length);
224
+ assertValidInterpolatePosterizeOption(options?.posterize);
216
225
  const easingOption = options?.easing;
217
226
  const defaultEasing = (num) => num;
218
227
  const resolveEasingForSegment = (segmentIndex) => {
@@ -235,8 +244,12 @@ function interpolate(input, inputRange, outputRange, options) {
235
244
  if (typeof input !== "number") {
236
245
  throw new TypeError("Cannot interpolate an input which is not a number");
237
246
  }
238
- const range = findRange(input, inputRange);
239
- return interpolateFunction(input, [inputRange[range], inputRange[range + 1]], [outputRange[range], outputRange[range + 1]], {
247
+ if (inputRange.length === 1) {
248
+ return outputRange[0];
249
+ }
250
+ const posterizedInput = options?.posterize === undefined ? input : Math.floor(input / options.posterize) * options.posterize;
251
+ const range = findRange(posterizedInput, inputRange);
252
+ return interpolateFunction(posterizedInput, [inputRange[range], inputRange[range + 1]], [outputRange[range], outputRange[range + 1]], {
240
253
  easing: resolveEasingForSegment(range),
241
254
  extrapolateLeft,
242
255
  extrapolateRight
@@ -1140,8 +1153,10 @@ try {
1140
1153
 
1141
1154
  // script-embed:render-video-script
1142
1155
  var script2 = `// src/scripts/render-video.ts
1143
- import { statSync } from "fs";
1156
+ import { randomUUID } from "crypto";
1157
+ import { stat, readFile, rename, writeFile } from "fs/promises";
1144
1158
  import { RenderInternals } from "@remotion/renderer";
1159
+ import { put } from "@vercel/blob";
1145
1160
 
1146
1161
  // ../core/dist/esm/no-react.mjs
1147
1162
  function interpolateFunction(input, inputRange, outputRange, options) {
@@ -1196,8 +1211,8 @@ function checkValidInputRange(arr) {
1196
1211
  }
1197
1212
  }
1198
1213
  function checkInfiniteRange(name, arr) {
1199
- if (arr.length < 2) {
1200
- throw new Error(name + " must have at least 2 elements");
1214
+ if (arr.length < 1) {
1215
+ throw new Error(name + " must have at least 1 element");
1201
1216
  }
1202
1217
  for (const element of arr) {
1203
1218
  if (typeof element !== "number") {
@@ -1225,6 +1240,14 @@ function assertValidInterpolateEasingOption(easing, inputRangeLength) {
1225
1240
  }
1226
1241
  }
1227
1242
  }
1243
+ function assertValidInterpolatePosterizeOption(posterize) {
1244
+ if (posterize === undefined) {
1245
+ return;
1246
+ }
1247
+ if (typeof posterize !== "number" || !Number.isFinite(posterize) || posterize <= 0) {
1248
+ throw new Error(\`posterize must be a positive finite number, but got \${posterize}\`);
1249
+ }
1250
+ }
1228
1251
  function interpolate(input, inputRange, outputRange, options) {
1229
1252
  if (typeof input === "undefined") {
1230
1253
  throw new Error("input can not be undefined");
@@ -1242,6 +1265,7 @@ function interpolate(input, inputRange, outputRange, options) {
1242
1265
  checkInfiniteRange("outputRange", outputRange);
1243
1266
  checkValidInputRange(inputRange);
1244
1267
  assertValidInterpolateEasingOption(options?.easing, inputRange.length);
1268
+ assertValidInterpolatePosterizeOption(options?.posterize);
1245
1269
  const easingOption = options?.easing;
1246
1270
  const defaultEasing = (num) => num;
1247
1271
  const resolveEasingForSegment = (segmentIndex) => {
@@ -1264,8 +1288,12 @@ function interpolate(input, inputRange, outputRange, options) {
1264
1288
  if (typeof input !== "number") {
1265
1289
  throw new TypeError("Cannot interpolate an input which is not a number");
1266
1290
  }
1267
- const range = findRange(input, inputRange);
1268
- return interpolateFunction(input, [inputRange[range], inputRange[range + 1]], [outputRange[range], outputRange[range + 1]], {
1291
+ if (inputRange.length === 1) {
1292
+ return outputRange[0];
1293
+ }
1294
+ const posterizedInput = options?.posterize === undefined ? input : Math.floor(input / options.posterize) * options.posterize;
1295
+ const range = findRange(posterizedInput, inputRange);
1296
+ return interpolateFunction(posterizedInput, [inputRange[range], inputRange[range + 1]], [outputRange[range], outputRange[range + 1]], {
1269
1297
  easing: resolveEasingForSegment(range),
1270
1298
  extrapolateLeft,
1271
1299
  extrapolateRight
@@ -2064,17 +2092,58 @@ var NoReactInternals = {
2064
2092
  };
2065
2093
 
2066
2094
  // src/scripts/render-video.ts
2095
+ var PROGRESS_FILE = "/vercel/sandbox/progress.json";
2067
2096
  var config = JSON.parse(process.argv[2]);
2068
2097
  var noop = () => {
2069
2098
  return;
2070
2099
  };
2100
+ var progressWrite = Promise.resolve();
2101
+ function getExtension(filePath) {
2102
+ const lastDot = filePath.lastIndexOf(".");
2103
+ if (lastDot === -1) {
2104
+ return "";
2105
+ }
2106
+ return filePath.slice(lastDot);
2107
+ }
2108
+ var writeProgress = (message) => {
2109
+ const tmpFile = \`\${PROGRESS_FILE}.tmp\`;
2110
+ progressWrite = progressWrite.then(async () => {
2111
+ await writeFile(tmpFile, JSON.stringify(message));
2112
+ await rename(tmpFile, PROGRESS_FILE);
2113
+ });
2114
+ return progressWrite;
2115
+ };
2116
+ var reportProgress = async (message) => {
2117
+ console.log(JSON.stringify(message));
2118
+ await writeProgress(message);
2119
+ };
2120
+ var uploadToVercelBlob = async ({
2121
+ sandboxFilePath,
2122
+ contentType,
2123
+ access,
2124
+ blobPath
2125
+ }) => {
2126
+ const blobToken = process.env.BLOB_READ_WRITE_TOKEN;
2127
+ if (!blobToken) {
2128
+ throw new Error("BLOB_READ_WRITE_TOKEN is not set.");
2129
+ }
2130
+ const actualBlobPath = blobPath ?? \`renders/\${randomUUID()}\${getExtension(sandboxFilePath)}\`;
2131
+ const fileBuffer = await readFile(sandboxFilePath);
2132
+ const { size } = await stat(sandboxFilePath);
2133
+ const blob = await put(actualBlobPath, fileBuffer, {
2134
+ access,
2135
+ contentType,
2136
+ token: blobToken
2137
+ });
2138
+ return { url: blob.downloadUrl, size };
2139
+ };
2071
2140
  try {
2072
2141
  const serializedInputProps = NoReactInternals.serializeJSONWithSpecialTypes({
2073
2142
  data: config.inputProps,
2074
2143
  indent: undefined,
2075
2144
  staticBase: null
2076
2145
  }).serializedString;
2077
- console.log(JSON.stringify({ stage: "opening-browser", overallProgress: 0 }));
2146
+ await reportProgress({ stage: "opening-browser", overallProgress: 0 });
2078
2147
  const browser = await RenderInternals.internalOpenBrowser({
2079
2148
  browser: "chrome",
2080
2149
  browserExecutable: config.browserExecutable,
@@ -2089,7 +2158,7 @@ try {
2089
2158
  }),
2090
2159
  chromeMode: config.chromeMode
2091
2160
  });
2092
- console.log(JSON.stringify({ stage: "selecting-composition", overallProgress: 0.02 }));
2161
+ await reportProgress({ stage: "selecting-composition", overallProgress: 0.02 });
2093
2162
  const { metadata: composition } = await RenderInternals.internalSelectComposition({
2094
2163
  serializedInputPropsWithCustomSchema: serializedInputProps,
2095
2164
  envVariables: config.envVariables,
@@ -2169,7 +2238,7 @@ try {
2169
2238
  sampleRate: config.sampleRate,
2170
2239
  puppeteerInstance: browser,
2171
2240
  onProgress: (progress) => {
2172
- console.log(JSON.stringify({
2241
+ reportProgress({
2173
2242
  stage: "render-progress",
2174
2243
  progress: {
2175
2244
  renderedFrames: progress.renderedFrames,
@@ -2180,8 +2249,10 @@ try {
2180
2249
  progress: progress.progress,
2181
2250
  stitchStage: progress.stitchStage
2182
2251
  },
2183
- overallProgress: 0.04 + progress.progress * 0.96
2184
- }));
2252
+ overallProgress: 0.04 + progress.progress * 0.94
2253
+ }).catch((error) => {
2254
+ console.error(error.message);
2255
+ });
2185
2256
  },
2186
2257
  onDownload: () => {
2187
2258
  return;
@@ -2203,12 +2274,44 @@ try {
2203
2274
  onProgress: noop
2204
2275
  })
2205
2276
  });
2206
- console.log(JSON.stringify({ stage: "render-complete", overallProgress: 1 }));
2277
+ await progressWrite;
2278
+ console.log(JSON.stringify({ stage: "render-complete", overallProgress: 0.98 }));
2207
2279
  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 }));
2280
+ const sandboxFilePath = config.outputLocation ?? "/tmp/video.mp4";
2281
+ if (config.vercelBlob) {
2282
+ await reportProgress({ stage: "uploading", overallProgress: 0.99 });
2283
+ const { url, size } = await uploadToVercelBlob({
2284
+ sandboxFilePath,
2285
+ contentType,
2286
+ access: config.vercelBlob.access,
2287
+ blobPath: config.vercelBlob.blobPath
2288
+ });
2289
+ await reportProgress({
2290
+ stage: "done",
2291
+ url,
2292
+ size,
2293
+ contentType,
2294
+ overallProgress: 1
2295
+ });
2296
+ } else {
2297
+ const { size } = await stat(sandboxFilePath);
2298
+ await reportProgress({
2299
+ stage: "done",
2300
+ size,
2301
+ contentType,
2302
+ overallProgress: 1
2303
+ });
2304
+ }
2210
2305
  } catch (err) {
2211
- console.error(err.message);
2306
+ const message = err.message;
2307
+ await writeProgress({
2308
+ stage: "error",
2309
+ message,
2310
+ overallProgress: 1
2311
+ }).catch(() => {
2312
+ return;
2313
+ });
2314
+ console.error(message);
2212
2315
  process.exit(1);
2213
2316
  }
2214
2317
  `;
@@ -2501,50 +2604,135 @@ async function createSandbox({
2501
2604
  await report(1, "Sandbox ready");
2502
2605
  return sandbox;
2503
2606
  }
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
2607
+ // src/get-render-progress.ts
2608
+ import { Sandbox as Sandbox2 } from "@vercel/sandbox";
2609
+ var PROGRESS_FILE = "/vercel/sandbox/progress.json";
2610
+ var isStoppedOrExpiredSandboxError = (error) => {
2611
+ if (typeof error === "object" && error !== null && "code" in error) {
2612
+ return error.code === "sandbox_stopped";
2613
+ }
2614
+ if (!(error instanceof Error)) {
2615
+ return false;
2616
+ }
2617
+ return error.message.includes("sandbox_stopped") || error.message.includes("Sandbox has stopped execution") || error.message.includes("no longer available");
2618
+ };
2619
+ var getCommandError = async (command) => {
2620
+ const stderr = await command.stderr().catch(() => "");
2621
+ const stdout = await command.stdout().catch(() => "");
2622
+ const output = [stderr, stdout].filter(Boolean).join(" ");
2623
+ return output || `Render command exited with code ${command.exitCode}.`;
2624
+ };
2625
+ async function getRenderProgress({
2626
+ sandboxId,
2627
+ cmdId
2547
2628
  }) {
2629
+ let sandbox;
2630
+ try {
2631
+ sandbox = await Sandbox2.get({ sandboxId });
2632
+ } catch {
2633
+ return { stage: "expired" };
2634
+ }
2635
+ let command;
2636
+ try {
2637
+ command = await sandbox.getCommand(cmdId);
2638
+ } catch (err) {
2639
+ if (isStoppedOrExpiredSandboxError(err)) {
2640
+ return { stage: "expired" };
2641
+ }
2642
+ return {
2643
+ stage: "error",
2644
+ message: err.message,
2645
+ overallProgress: 1
2646
+ };
2647
+ }
2648
+ let buffer;
2649
+ try {
2650
+ buffer = await sandbox.readFileToBuffer({ path: PROGRESS_FILE });
2651
+ } catch (err) {
2652
+ if (isStoppedOrExpiredSandboxError(err)) {
2653
+ return { stage: "expired" };
2654
+ }
2655
+ return {
2656
+ stage: "error",
2657
+ message: err.message,
2658
+ overallProgress: 1
2659
+ };
2660
+ }
2661
+ if (!buffer) {
2662
+ if (command.exitCode === null) {
2663
+ return { stage: "starting", overallProgress: 0 };
2664
+ }
2665
+ const message = await getCommandError(command);
2666
+ return { stage: "error", message, overallProgress: 1 };
2667
+ }
2668
+ let progress;
2669
+ try {
2670
+ progress = JSON.parse(buffer.toString("utf-8"));
2671
+ } catch {
2672
+ return {
2673
+ stage: "error",
2674
+ message: "Could not parse the render progress file.",
2675
+ overallProgress: 1
2676
+ };
2677
+ }
2678
+ if (command.exitCode !== null && command.exitCode !== 0) {
2679
+ const message = await getCommandError(command);
2680
+ return { stage: "error", message, overallProgress: 1 };
2681
+ }
2682
+ return progress;
2683
+ }
2684
+ // src/render-media-on-vercel.ts
2685
+ var DEFAULT_DETACHED_SANDBOX_TIMEOUT = 30 * 60 * 1000;
2686
+ var internalRenderMediaOnVercel = async (options) => {
2687
+ const {
2688
+ sandbox,
2689
+ compositionId,
2690
+ inputProps,
2691
+ onProgress,
2692
+ outputFile = "/tmp/video.mp4",
2693
+ codec = "h264",
2694
+ crf,
2695
+ imageFormat,
2696
+ pixelFormat,
2697
+ envVariables = {},
2698
+ frameRange,
2699
+ everyNthFrame = 1,
2700
+ proResProfile,
2701
+ chromiumOptions = {},
2702
+ scale = 1,
2703
+ preferLossless = false,
2704
+ enforceAudioTrack = false,
2705
+ disallowParallelEncoding = false,
2706
+ concurrency,
2707
+ metadata,
2708
+ licenseKey,
2709
+ videoBitrate,
2710
+ audioBitrate,
2711
+ encodingMaxRate,
2712
+ encodingBufferSize,
2713
+ muted = false,
2714
+ numberOfGifLoops,
2715
+ x264Preset,
2716
+ gopSize,
2717
+ colorSpace = "default",
2718
+ jpegQuality = 80,
2719
+ audioCodec,
2720
+ logLevel = "info",
2721
+ timeoutInMilliseconds = 30000,
2722
+ forSeamlessAacConcatenation = false,
2723
+ separateAudioTo,
2724
+ hardwareAcceleration = "disable",
2725
+ offthreadVideoCacheSizeInBytes,
2726
+ mediaCacheSizeInBytes,
2727
+ offthreadVideoThreads,
2728
+ sampleRate,
2729
+ detached = false,
2730
+ detachedSandboxTimeoutInMilliseconds = DEFAULT_DETACHED_SANDBOX_TIMEOUT
2731
+ } = options;
2732
+ const vercelBlob = options.detached ? options.vercelBlob : undefined;
2733
+ if (detached && !vercelBlob) {
2734
+ throw new Error("The vercelBlob option is required when detached is set to true.");
2735
+ }
2548
2736
  const serveUrl = `/vercel/sandbox/${REMOTION_SANDBOX_BUNDLE_DIR}`;
2549
2737
  const renderConfig = {
2550
2738
  serveUrl,
@@ -2590,13 +2778,26 @@ async function renderMediaOnVercel({
2590
2778
  browserExecutable: null,
2591
2779
  binariesDirectory: null,
2592
2780
  repro: false,
2593
- sampleRate: sampleRate ?? 48000
2781
+ sampleRate: sampleRate ?? 48000,
2782
+ vercelBlob: vercelBlob ? {
2783
+ blobPath: vercelBlob.blobPath ?? null,
2784
+ access: vercelBlob.access
2785
+ } : null
2594
2786
  };
2595
2787
  const renderCmd = await sandbox.runCommand({
2596
2788
  cmd: "node",
2597
2789
  args: ["render-video.mjs", JSON.stringify(renderConfig)],
2598
- detached: true
2790
+ detached: true,
2791
+ env: vercelBlob ? { BLOB_READ_WRITE_TOKEN: vercelBlob.blobToken } : undefined
2599
2792
  });
2793
+ if (detached) {
2794
+ await sandbox.extendTimeout(detachedSandboxTimeoutInMilliseconds);
2795
+ return {
2796
+ sandboxId: sandbox.sandboxId,
2797
+ cmdId: renderCmd.cmdId,
2798
+ outputFile
2799
+ };
2800
+ }
2600
2801
  let contentType = "application/octet-stream";
2601
2802
  for await (const log of renderCmd.logs()) {
2602
2803
  if (log.stream === "stdout") {
@@ -2617,7 +2818,8 @@ async function renderMediaOnVercel({
2617
2818
  throw new Error(`Render failed: ${stderr} ${stdout}`);
2618
2819
  }
2619
2820
  return { sandboxFilePath: outputFile, contentType };
2620
- }
2821
+ };
2822
+ var renderMediaOnVercel = internalRenderMediaOnVercel;
2621
2823
  // src/render-still-on-vercel.ts
2622
2824
  async function renderStillOnVercel({
2623
2825
  sandbox,
@@ -2749,6 +2951,7 @@ export {
2749
2951
  uploadToVercelBlob,
2750
2952
  renderStillOnVercel,
2751
2953
  renderMediaOnVercel,
2954
+ getRenderProgress,
2752
2955
  createSandbox,
2753
2956
  addBundleToSandbox
2754
2957
  };
@@ -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.468",
3
+ "version": "4.0.470",
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.468",
27
- "remotion": "4.0.468"
26
+ "@remotion/renderer": "4.0.470",
27
+ "remotion": "4.0.470"
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.468",
41
+ "@remotion/eslint-config-internal": "4.0.470",
42
42
  "@vercel/blob": "2.3.0",
43
43
  "@vercel/sandbox": "1.6.0",
44
44
  "eslint": "9.19.0",