@remotion/lambda-client 4.0.521 → 4.0.523

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/cjs/index.js CHANGED
@@ -72216,7 +72216,7 @@ var validateDownloadBehavior = (downloadBehavior) => {
72216
72216
  }
72217
72217
  }
72218
72218
  };
72219
- var VERSION = "4.0.521";
72219
+ var VERSION = "4.0.523";
72220
72220
  var isColorSupported = () => {
72221
72221
  const env = process.env || {};
72222
72222
  const isForceDisabled = "NO_COLOR" in env;
@@ -73320,7 +73320,7 @@ var DEFAULT = null;
73320
73320
  var cliFlag = "separate-audio-to";
73321
73321
  var separateAudioOption = {
73322
73322
  cliFlag,
73323
- description: () => `If set, the audio will not be included in the main output but rendered as a separate file at the location you pass. It is recommended to use an absolute path. If a relative path is passed, it is relative to the Remotion Root.`,
73323
+ description: () => `If set, the audio will not be included in the main output but rendered as a separate file at the location you pass. If the render contains no audio, a silent audio file is produced even when enforceAudioTrack is false. The muted option still takes precedence. It is recommended to use an absolute path. If a relative path is passed, it is relative to the Remotion Root.`,
73324
73324
  docLink: "https://remotion.dev/docs/renderer/render-media",
73325
73325
  getValue: ({ commandLine }) => {
73326
73326
  if (commandLine[cliFlag]) {
@@ -73663,6 +73663,9 @@ var getExpectedOutName = ({
73663
73663
  }
73664
73664
  throw new TypeError("no type passed");
73665
73665
  };
73666
+
73667
+ class OutputFileAccessDeniedError extends Error {
73668
+ }
73666
73669
  var findOutputFileInBucket = async ({
73667
73670
  region,
73668
73671
  renderMetadata,
@@ -73701,9 +73704,6 @@ var findOutputFileInBucket = async ({
73701
73704
  if (err.name === "NotFound") {
73702
73705
  return null;
73703
73706
  }
73704
- if (err.message === "UnknownError" || err.$metadata?.httpStatusCode === 403) {
73705
- throw new Error(`Unable to access item "${key}" from bucket "${renderBucketName}" ${customCredentials?.endpoint ? `(S3 Endpoint = ${customCredentials?.endpoint})` : ""} - got a 403 error when heading the file. Check your credentials and permissions. The Lambda role must have permission for both "s3:GetObject" and "s3:ListBucket" actions.`, { cause: err });
73706
- }
73707
73707
  throw err;
73708
73708
  }
73709
73709
  };
@@ -74113,7 +74113,7 @@ var getProgress = async ({
74113
74113
  });
74114
74114
  const isBeyondTimeoutAndMissingChunks = Date.now() > renderMetadata.startedDate + timeoutInMilliseconds + 20000 && missingChunks && missingChunks.length > 0;
74115
74115
  const isBeyondTimeoutAndHasStitchTimeout = Date.now() > renderMetadata.startedDate + timeoutInMilliseconds * 2 + 20000;
74116
- const shouldCheckForCompletedOutput = allChunks && (isBeyondTimeoutAndHasStitchTimeout || overallProgress.combinedFrames >= frameCount && overallProgress.timeToCombine !== null);
74116
+ const shouldCheckForCompletedOutput = allChunks && !errorExplanations.some((error) => error.isFatal && !error.willRetry) && (isBeyondTimeoutAndHasStitchTimeout || overallProgress.combinedFrames >= frameCount && overallProgress.timeToCombine !== null);
74117
74117
  if (shouldCheckForCompletedOutput) {
74118
74118
  const outputFile = await findOutputFileInBucket({
74119
74119
  bucketName,
@@ -74124,6 +74124,11 @@ var getProgress = async ({
74124
74124
  providerSpecifics,
74125
74125
  forcePathStyle,
74126
74126
  requestHandler
74127
+ }).catch((err) => {
74128
+ if (err instanceof OutputFileAccessDeniedError) {
74129
+ return null;
74130
+ }
74131
+ throw err;
74127
74132
  });
74128
74133
  if (outputFile) {
74129
74134
  const outData = getExpectedOutName({
@@ -76240,16 +76245,24 @@ var lambdaHeadFileImplementation = async ({
76240
76245
  forcePathStyle,
76241
76246
  requestHandler
76242
76247
  }) => {
76243
- const head = await getS3Client({
76244
- region,
76245
- customCredentials,
76246
- forcePathStyle,
76247
- requestHandler
76248
- }).send(new import_client_s36.HeadObjectCommand({
76249
- Bucket: bucketName,
76250
- Key: key
76251
- }));
76252
- return head;
76248
+ try {
76249
+ const head = await getS3Client({
76250
+ region,
76251
+ customCredentials,
76252
+ forcePathStyle,
76253
+ requestHandler
76254
+ }).send(new import_client_s36.HeadObjectCommand({
76255
+ Bucket: bucketName,
76256
+ Key: key
76257
+ }));
76258
+ return head;
76259
+ } catch (err) {
76260
+ if (err.message === "UnknownError" || err.$metadata?.httpStatusCode === 403) {
76261
+ const ErrorClass = err.$metadata?.httpStatusCode === 403 ? OutputFileAccessDeniedError : Error;
76262
+ throw new ErrorClass(`Unable to access item "${key}" from bucket "${bucketName}" ${customCredentials?.endpoint ? `(S3 Endpoint = ${customCredentials?.endpoint})` : ""} - got a 403 error when heading the file. Check your credentials and permissions. The Lambda role must have permission for both "s3:GetObject" and "s3:ListBucket" actions.`, { cause: err });
76263
+ }
76264
+ throw err;
76265
+ }
76253
76266
  };
76254
76267
 
76255
76268
  // src/is-flaky-error.ts
@@ -76624,7 +76637,8 @@ var tryLambdaWriteFile = async ({
76624
76637
  customCredentials,
76625
76638
  forcePathStyle,
76626
76639
  storageClass,
76627
- requestHandler
76640
+ requestHandler,
76641
+ ifNotExists
76628
76642
  }) => {
76629
76643
  const client = getS3Client({
76630
76644
  region,
@@ -76640,7 +76654,8 @@ var tryLambdaWriteFile = async ({
76640
76654
  ExpectedBucketOwner: customCredentials ? undefined : expectedBucketOwner ?? undefined,
76641
76655
  ContentType: import_mime_types.default.lookup(key) || "application/octet-stream",
76642
76656
  ContentDisposition: getContentDispositionHeader(downloadBehavior),
76643
- StorageClass: storageClass ?? undefined
76657
+ StorageClass: storageClass ?? undefined,
76658
+ IfNoneMatch: ifNotExists ? "*" : undefined
76644
76659
  };
76645
76660
  const size = body instanceof Buffer || body instanceof Uint8Array ? body.length : body instanceof Blob ? body.size : typeof body === "string" ? Buffer.from(body).length : null;
76646
76661
  if (size === null || size > MULTIPART_THRESHOLD) {
@@ -76650,16 +76665,32 @@ var tryLambdaWriteFile = async ({
76650
76665
  queueSize: 4,
76651
76666
  partSize: 5 * 1024 * 1024
76652
76667
  });
76653
- await upload.done();
76668
+ try {
76669
+ await upload.done();
76670
+ } catch (err) {
76671
+ const status = err.$metadata?.httpStatusCode;
76672
+ if (ifNotExists && upload.uploadId && (status === 412 || status === 409)) {
76673
+ await client.send(new import_client_s310.AbortMultipartUploadCommand({
76674
+ Bucket: bucketName,
76675
+ Key: key,
76676
+ UploadId: upload.uploadId,
76677
+ ExpectedBucketOwner: params.ExpectedBucketOwner
76678
+ })).catch(() => {});
76679
+ }
76680
+ throw err;
76681
+ }
76654
76682
  } else {
76655
76683
  await client.send(new import_client_s310.PutObjectCommand(params));
76656
76684
  }
76657
76685
  };
76658
- var lambdaWriteFileImplementation = async (params) => {
76686
+ var writeFileWithRetries = async (params) => {
76659
76687
  const remainingRetries = params.retries ?? 2;
76660
76688
  try {
76661
76689
  await tryLambdaWriteFile(params);
76662
76690
  } catch (err) {
76691
+ if (params.ifNotExists && err.$metadata?.httpStatusCode === 412) {
76692
+ throw new Error(`Output file "${params.key}" in bucket "${params.bucketName}" already exists. Delete it before re-rendering, or set the 'overwrite' option in renderMediaOnLambda() to overwrite it.`, { cause: err });
76693
+ }
76663
76694
  const bodyCanBeRetried = typeof params.body === "string" || params.body instanceof Uint8Array;
76664
76695
  if (remainingRetries === 0 || !bodyCanBeRetried) {
76665
76696
  throw err;
@@ -76671,12 +76702,19 @@ var lambdaWriteFileImplementation = async (params) => {
76671
76702
  console.warn("Failed to write file to storage:");
76672
76703
  console.warn(err);
76673
76704
  console.warn(`Retrying (${remainingRetries} retries remaining)...`);
76674
- return lambdaWriteFileImplementation({
76705
+ return writeFileWithRetries({
76675
76706
  ...params,
76676
76707
  retries: remainingRetries - 1
76677
76708
  });
76678
76709
  }
76679
76710
  };
76711
+ var lambdaWriteFileImplementation = (params) => writeFileWithRetries({ ...params, ifNotExists: false });
76712
+ var lambdaWriteFileIfNotExistsImplementation = (params) => {
76713
+ if (params.customCredentials !== null) {
76714
+ throw new Error("Conditional output uploads are only supported for AWS S3");
76715
+ }
76716
+ return writeFileWithRetries({ ...params, ifNotExists: true });
76717
+ };
76680
76718
 
76681
76719
  // src/aws-provider.ts
76682
76720
  if (/^AWS_Lambda_nodejs(?:18|20|24)[.]x$/.test(process.env.AWS_EXECUTION_ENV ?? "") === true) {
@@ -76714,6 +76752,8 @@ var awsImplementation = {
76714
76752
  randomHash: randomHashImplementation,
76715
76753
  readFile: lambdaReadFileImplementation,
76716
76754
  writeFile: lambdaWriteFileImplementation,
76755
+ supportsConditionalOutput: ({ customCredentials }) => customCredentials === null,
76756
+ writeFileIfNotExists: lambdaWriteFileIfNotExistsImplementation,
76717
76757
  headFile: lambdaHeadFileImplementation,
76718
76758
  convertToServeUrl: convertToServeUrlImplementation,
76719
76759
  printLoggingHelper: true,
@@ -3,3 +3,4 @@ import type { AwsProvider } from './aws-provider';
3
3
  export declare const lambdaWriteFileImplementation: (params: WriteFileInput<AwsProvider> & {
4
4
  retries?: number | undefined;
5
5
  }) => Promise<void>;
6
+ export declare const lambdaWriteFileIfNotExistsImplementation: (params: WriteFileInput<AwsProvider>) => Promise<void>;
@@ -71558,7 +71558,7 @@ var validateDownloadBehavior = (downloadBehavior) => {
71558
71558
  }
71559
71559
  }
71560
71560
  };
71561
- var VERSION = "4.0.521";
71561
+ var VERSION = "4.0.523";
71562
71562
  var isColorSupported = () => {
71563
71563
  const env = process.env || {};
71564
71564
  const isForceDisabled = "NO_COLOR" in env;
@@ -72662,7 +72662,7 @@ var DEFAULT = null;
72662
72662
  var cliFlag = "separate-audio-to";
72663
72663
  var separateAudioOption = {
72664
72664
  cliFlag,
72665
- description: () => `If set, the audio will not be included in the main output but rendered as a separate file at the location you pass. It is recommended to use an absolute path. If a relative path is passed, it is relative to the Remotion Root.`,
72665
+ description: () => `If set, the audio will not be included in the main output but rendered as a separate file at the location you pass. If the render contains no audio, a silent audio file is produced even when enforceAudioTrack is false. The muted option still takes precedence. It is recommended to use an absolute path. If a relative path is passed, it is relative to the Remotion Root.`,
72666
72666
  docLink: "https://remotion.dev/docs/renderer/render-media",
72667
72667
  getValue: ({ commandLine }) => {
72668
72668
  if (commandLine[cliFlag]) {
@@ -73005,6 +73005,9 @@ var getExpectedOutName = ({
73005
73005
  }
73006
73006
  throw new TypeError("no type passed");
73007
73007
  };
73008
+
73009
+ class OutputFileAccessDeniedError extends Error {
73010
+ }
73008
73011
  var findOutputFileInBucket = async ({
73009
73012
  region,
73010
73013
  renderMetadata,
@@ -73043,9 +73046,6 @@ var findOutputFileInBucket = async ({
73043
73046
  if (err.name === "NotFound") {
73044
73047
  return null;
73045
73048
  }
73046
- if (err.message === "UnknownError" || err.$metadata?.httpStatusCode === 403) {
73047
- throw new Error(`Unable to access item "${key}" from bucket "${renderBucketName}" ${customCredentials?.endpoint ? `(S3 Endpoint = ${customCredentials?.endpoint})` : ""} - got a 403 error when heading the file. Check your credentials and permissions. The Lambda role must have permission for both "s3:GetObject" and "s3:ListBucket" actions.`, { cause: err });
73048
- }
73049
73049
  throw err;
73050
73050
  }
73051
73051
  };
@@ -73455,7 +73455,7 @@ var getProgress = async ({
73455
73455
  });
73456
73456
  const isBeyondTimeoutAndMissingChunks = Date.now() > renderMetadata.startedDate + timeoutInMilliseconds + 20000 && missingChunks && missingChunks.length > 0;
73457
73457
  const isBeyondTimeoutAndHasStitchTimeout = Date.now() > renderMetadata.startedDate + timeoutInMilliseconds * 2 + 20000;
73458
- const shouldCheckForCompletedOutput = allChunks && (isBeyondTimeoutAndHasStitchTimeout || overallProgress.combinedFrames >= frameCount && overallProgress.timeToCombine !== null);
73458
+ const shouldCheckForCompletedOutput = allChunks && !errorExplanations.some((error) => error.isFatal && !error.willRetry) && (isBeyondTimeoutAndHasStitchTimeout || overallProgress.combinedFrames >= frameCount && overallProgress.timeToCombine !== null);
73459
73459
  if (shouldCheckForCompletedOutput) {
73460
73460
  const outputFile = await findOutputFileInBucket({
73461
73461
  bucketName,
@@ -73466,6 +73466,11 @@ var getProgress = async ({
73466
73466
  providerSpecifics,
73467
73467
  forcePathStyle,
73468
73468
  requestHandler
73469
+ }).catch((err) => {
73470
+ if (err instanceof OutputFileAccessDeniedError) {
73471
+ return null;
73472
+ }
73473
+ throw err;
73469
73474
  });
73470
73475
  if (outputFile) {
73471
73476
  const outData = getExpectedOutName({
@@ -75582,16 +75587,24 @@ var lambdaHeadFileImplementation = async ({
75582
75587
  forcePathStyle,
75583
75588
  requestHandler
75584
75589
  }) => {
75585
- const head = await getS3Client({
75586
- region,
75587
- customCredentials,
75588
- forcePathStyle,
75589
- requestHandler
75590
- }).send(new import_client_s36.HeadObjectCommand({
75591
- Bucket: bucketName,
75592
- Key: key
75593
- }));
75594
- return head;
75590
+ try {
75591
+ const head = await getS3Client({
75592
+ region,
75593
+ customCredentials,
75594
+ forcePathStyle,
75595
+ requestHandler
75596
+ }).send(new import_client_s36.HeadObjectCommand({
75597
+ Bucket: bucketName,
75598
+ Key: key
75599
+ }));
75600
+ return head;
75601
+ } catch (err) {
75602
+ if (err.message === "UnknownError" || err.$metadata?.httpStatusCode === 403) {
75603
+ const ErrorClass = err.$metadata?.httpStatusCode === 403 ? OutputFileAccessDeniedError : Error;
75604
+ throw new ErrorClass(`Unable to access item "${key}" from bucket "${bucketName}" ${customCredentials?.endpoint ? `(S3 Endpoint = ${customCredentials?.endpoint})` : ""} - got a 403 error when heading the file. Check your credentials and permissions. The Lambda role must have permission for both "s3:GetObject" and "s3:ListBucket" actions.`, { cause: err });
75605
+ }
75606
+ throw err;
75607
+ }
75595
75608
  };
75596
75609
 
75597
75610
  // src/is-flaky-error.ts
@@ -76450,7 +76463,8 @@ var tryLambdaWriteFile = async ({
76450
76463
  customCredentials,
76451
76464
  forcePathStyle,
76452
76465
  storageClass,
76453
- requestHandler
76466
+ requestHandler,
76467
+ ifNotExists
76454
76468
  }) => {
76455
76469
  const client = getS3Client({
76456
76470
  region,
@@ -76466,7 +76480,8 @@ var tryLambdaWriteFile = async ({
76466
76480
  ExpectedBucketOwner: customCredentials ? undefined : expectedBucketOwner ?? undefined,
76467
76481
  ContentType: import_mime_types.default.lookup(key) || "application/octet-stream",
76468
76482
  ContentDisposition: getContentDispositionHeader(downloadBehavior),
76469
- StorageClass: storageClass ?? undefined
76483
+ StorageClass: storageClass ?? undefined,
76484
+ IfNoneMatch: ifNotExists ? "*" : undefined
76470
76485
  };
76471
76486
  const size = body instanceof Buffer || body instanceof Uint8Array ? body.length : body instanceof Blob ? body.size : typeof body === "string" ? Buffer.from(body).length : null;
76472
76487
  if (size === null || size > MULTIPART_THRESHOLD) {
@@ -76476,16 +76491,32 @@ var tryLambdaWriteFile = async ({
76476
76491
  queueSize: 4,
76477
76492
  partSize: 5 * 1024 * 1024
76478
76493
  });
76479
- await upload.done();
76494
+ try {
76495
+ await upload.done();
76496
+ } catch (err) {
76497
+ const status = err.$metadata?.httpStatusCode;
76498
+ if (ifNotExists && upload.uploadId && (status === 412 || status === 409)) {
76499
+ await client.send(new import_client_s310.AbortMultipartUploadCommand({
76500
+ Bucket: bucketName,
76501
+ Key: key,
76502
+ UploadId: upload.uploadId,
76503
+ ExpectedBucketOwner: params.ExpectedBucketOwner
76504
+ })).catch(() => {});
76505
+ }
76506
+ throw err;
76507
+ }
76480
76508
  } else {
76481
76509
  await client.send(new import_client_s310.PutObjectCommand(params));
76482
76510
  }
76483
76511
  };
76484
- var lambdaWriteFileImplementation = async (params) => {
76512
+ var writeFileWithRetries = async (params) => {
76485
76513
  const remainingRetries = params.retries ?? 2;
76486
76514
  try {
76487
76515
  await tryLambdaWriteFile(params);
76488
76516
  } catch (err) {
76517
+ if (params.ifNotExists && err.$metadata?.httpStatusCode === 412) {
76518
+ throw new Error(`Output file "${params.key}" in bucket "${params.bucketName}" already exists. Delete it before re-rendering, or set the 'overwrite' option in renderMediaOnLambda() to overwrite it.`, { cause: err });
76519
+ }
76489
76520
  const bodyCanBeRetried = typeof params.body === "string" || params.body instanceof Uint8Array;
76490
76521
  if (remainingRetries === 0 || !bodyCanBeRetried) {
76491
76522
  throw err;
@@ -76497,12 +76528,19 @@ var lambdaWriteFileImplementation = async (params) => {
76497
76528
  console.warn("Failed to write file to storage:");
76498
76529
  console.warn(err);
76499
76530
  console.warn(`Retrying (${remainingRetries} retries remaining)...`);
76500
- return lambdaWriteFileImplementation({
76531
+ return writeFileWithRetries({
76501
76532
  ...params,
76502
76533
  retries: remainingRetries - 1
76503
76534
  });
76504
76535
  }
76505
76536
  };
76537
+ var lambdaWriteFileImplementation = (params) => writeFileWithRetries({ ...params, ifNotExists: false });
76538
+ var lambdaWriteFileIfNotExistsImplementation = (params) => {
76539
+ if (params.customCredentials !== null) {
76540
+ throw new Error("Conditional output uploads are only supported for AWS S3");
76541
+ }
76542
+ return writeFileWithRetries({ ...params, ifNotExists: true });
76543
+ };
76506
76544
 
76507
76545
  // src/aws-provider.ts
76508
76546
  if (/^AWS_Lambda_nodejs(?:18|20|24)[.]x$/.test(process.env.AWS_EXECUTION_ENV ?? "") === true) {
@@ -76540,6 +76578,8 @@ var awsImplementation = {
76540
76578
  randomHash: randomHashImplementation,
76541
76579
  readFile: lambdaReadFileImplementation,
76542
76580
  writeFile: lambdaWriteFileImplementation,
76581
+ supportsConditionalOutput: ({ customCredentials }) => customCredentials === null,
76582
+ writeFileIfNotExists: lambdaWriteFileIfNotExistsImplementation,
76543
76583
  headFile: lambdaHeadFileImplementation,
76544
76584
  convertToServeUrl: convertToServeUrlImplementation,
76545
76585
  printLoggingHelper: true,
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/lambda-client"
4
4
  },
5
5
  "name": "@remotion/lambda-client",
6
- "version": "4.0.521",
6
+ "version": "4.0.523",
7
7
  "main": "dist/cjs/index.js",
8
8
  "scripts": {
9
9
  "formatting": "oxfmt src --check",
@@ -26,12 +26,12 @@
26
26
  "@aws-sdk/lib-storage": "3.986.0",
27
27
  "mime-types": "2.1.34",
28
28
  "@aws-sdk/credential-provider-ini": "3.972.5",
29
- "@remotion/serverless-client": "4.0.521",
29
+ "@remotion/serverless-client": "4.0.523",
30
30
  "@types/express": "5.0.1",
31
31
  "express": "4.21.0",
32
- "@remotion/eslint-config-internal": "4.0.521",
32
+ "@remotion/eslint-config-internal": "4.0.523",
33
33
  "eslint": "9.19.0",
34
- "next": "16.2.11",
34
+ "next": "16.3.3",
35
35
  "@types/mime-types": "2.1.1",
36
36
  "@typescript/native-preview": "7.0.0-dev.20260217.1"
37
37
  },