@remotion/lambda-client 4.0.261

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 (227) hide show
  1. package/.turbo/turbo-make.log +6 -0
  2. package/LICENSE.md +49 -0
  3. package/README.md +5 -0
  4. package/bundle.ts +20 -0
  5. package/dist/app-router-webhook.d.ts +10 -0
  6. package/dist/app-router-webhook.js +43 -0
  7. package/dist/apply-lifecycle.d.ts +8 -0
  8. package/dist/apply-lifecycle.js +18 -0
  9. package/dist/aws-clients.d.ts +11 -0
  10. package/dist/aws-clients.js +51 -0
  11. package/dist/aws-provider.d.ts +23 -0
  12. package/dist/aws-provider.js +94 -0
  13. package/dist/bucket-exists.d.ts +3 -0
  14. package/dist/bucket-exists.js +26 -0
  15. package/dist/call-lambda-async.d.ts +2 -0
  16. package/dist/call-lambda-async.js +20 -0
  17. package/dist/call-lambda-streaming.d.ts +6 -0
  18. package/dist/call-lambda-streaming.js +125 -0
  19. package/dist/call-lambda-sync.d.ts +2 -0
  20. package/dist/call-lambda-sync.js +30 -0
  21. package/dist/check-credentials.d.ts +1 -0
  22. package/dist/check-credentials.js +39 -0
  23. package/dist/clean-items.d.ts +16 -0
  24. package/dist/clean-items.js +25 -0
  25. package/dist/constants.d.ts +25 -0
  26. package/dist/constants.js +26 -0
  27. package/dist/content-disposition-header.d.ts +2 -0
  28. package/dist/content-disposition-header.js +50 -0
  29. package/dist/convert-to-serve-url.d.ts +6 -0
  30. package/dist/convert-to-serve-url.js +14 -0
  31. package/dist/create-bucket.d.ts +3 -0
  32. package/dist/create-bucket.js +45 -0
  33. package/dist/delete-file.d.ts +3 -0
  34. package/dist/delete-file.js +12 -0
  35. package/dist/delete-function.d.ts +4 -0
  36. package/dist/delete-function.js +15 -0
  37. package/dist/delete-render.d.ts +20 -0
  38. package/dist/delete-render.js +84 -0
  39. package/dist/encode-aws-url-params.d.ts +1 -0
  40. package/dist/encode-aws-url-params.js +7 -0
  41. package/dist/esm/constants.mjs +45 -0
  42. package/dist/esm/index.mjs +6516 -0
  43. package/dist/esm/regions.mjs +50 -0
  44. package/dist/estimate-price.d.ts +17 -0
  45. package/dist/estimate-price.js +45 -0
  46. package/dist/express-webhook.d.ts +3 -0
  47. package/dist/express-webhook.js +46 -0
  48. package/dist/get-account-id.d.ts +3 -0
  49. package/dist/get-account-id.js +15 -0
  50. package/dist/get-aws-client.d.ts +30 -0
  51. package/dist/get-aws-client.js +56 -0
  52. package/dist/get-aws-urls.d.ts +25 -0
  53. package/dist/get-aws-urls.js +31 -0
  54. package/dist/get-buckets.d.ts +9 -0
  55. package/dist/get-buckets.js +62 -0
  56. package/dist/get-compositions-on-lambda.d.ts +18 -0
  57. package/dist/get-compositions-on-lambda.js +59 -0
  58. package/dist/get-credentials.d.ts +9 -0
  59. package/dist/get-credentials.js +55 -0
  60. package/dist/get-env-variable.d.ts +1 -0
  61. package/dist/get-env-variable.js +15 -0
  62. package/dist/get-function-name.d.ts +8 -0
  63. package/dist/get-function-name.js +17 -0
  64. package/dist/get-function-version.d.ts +7 -0
  65. package/dist/get-function-version.js +32 -0
  66. package/dist/get-functions.d.ts +8 -0
  67. package/dist/get-functions.js +77 -0
  68. package/dist/get-output-url-from-metadata.d.ts +3 -0
  69. package/dist/get-output-url-from-metadata.js +18 -0
  70. package/dist/get-render-progress.d.ts +15 -0
  71. package/dist/get-render-progress.js +45 -0
  72. package/dist/get-s3-client.d.ts +9 -0
  73. package/dist/get-s3-client.js +14 -0
  74. package/dist/get-service-client.d.ts +23 -0
  75. package/dist/get-service-client.js +120 -0
  76. package/dist/get-sites.d.ts +29 -0
  77. package/dist/get-sites.js +79 -0
  78. package/dist/head-file.d.ts +3 -0
  79. package/dist/head-file.js +17 -0
  80. package/dist/index.d.ts +123 -0
  81. package/dist/index.js +104 -0
  82. package/dist/is-cli.d.ts +2 -0
  83. package/dist/is-cli.js +10 -0
  84. package/dist/is-flaky-error.d.ts +1 -0
  85. package/dist/is-flaky-error.js +77 -0
  86. package/dist/is-in-lambda.d.ts +1 -0
  87. package/dist/is-in-lambda.js +9 -0
  88. package/dist/is-likely-to-have-aws-profile.d.ts +1 -0
  89. package/dist/is-likely-to-have-aws-profile.js +50 -0
  90. package/dist/lambda-version-string.d.ts +1 -0
  91. package/dist/lambda-version-string.js +7 -0
  92. package/dist/lifecycle-rules.d.ts +10 -0
  93. package/dist/lifecycle-rules.js +61 -0
  94. package/dist/lifecycle.d.ts +7 -0
  95. package/dist/lifecycle.js +24 -0
  96. package/dist/list-objects.d.ts +3 -0
  97. package/dist/list-objects.js +67 -0
  98. package/dist/make-lambda-payload.d.ts +54 -0
  99. package/dist/make-lambda-payload.js +148 -0
  100. package/dist/make-s3-url.d.ts +6 -0
  101. package/dist/make-s3-url.js +7 -0
  102. package/dist/p-limit.d.ts +1 -0
  103. package/dist/p-limit.js +57 -0
  104. package/dist/pages-router-webhook.d.ts +5 -0
  105. package/dist/pages-router-webhook.js +48 -0
  106. package/dist/parse-function-name.d.ts +8 -0
  107. package/dist/parse-function-name.js +17 -0
  108. package/dist/presign-url.d.ts +14 -0
  109. package/dist/presign-url.js +64 -0
  110. package/dist/price-per-1s.d.ts +37 -0
  111. package/dist/price-per-1s.js +822 -0
  112. package/dist/random-hash.d.ts +1 -0
  113. package/dist/random-hash.js +13 -0
  114. package/dist/read-file.d.ts +9 -0
  115. package/dist/read-file.js +18 -0
  116. package/dist/regions.d.ts +3 -0
  117. package/dist/regions.js +48 -0
  118. package/dist/render-media-on-lambda.d.ts +61 -0
  119. package/dist/render-media-on-lambda.js +127 -0
  120. package/dist/render-still-on-lambda.d.ts +53 -0
  121. package/dist/render-still-on-lambda.js +118 -0
  122. package/dist/runtime-preference.d.ts +2 -0
  123. package/dist/runtime-preference.js +8 -0
  124. package/dist/speculate-function-name.d.ts +6 -0
  125. package/dist/speculate-function-name.js +20 -0
  126. package/dist/test/encode-aws-url.test.d.ts +1 -0
  127. package/dist/test/encode-aws-url.test.js +8 -0
  128. package/dist/test/price-calculation.test.d.ts +1 -0
  129. package/dist/test/price-calculation.test.js +61 -0
  130. package/dist/test/pricing.test.d.ts +1 -0
  131. package/dist/test/pricing.test.js +27 -0
  132. package/dist/test/validate-disk-size-in-mb.test.d.ts +1 -0
  133. package/dist/test/validate-disk-size-in-mb.test.js +14 -0
  134. package/dist/validate-aws-region.d.ts +2 -0
  135. package/dist/validate-aws-region.js +9 -0
  136. package/dist/validate-bucketname.d.ts +4 -0
  137. package/dist/validate-bucketname.js +15 -0
  138. package/dist/validate-disk-size-in-mb.d.ts +1 -0
  139. package/dist/validate-disk-size-in-mb.js +23 -0
  140. package/dist/validate-lambda-codec.d.ts +2 -0
  141. package/dist/validate-lambda-codec.js +21 -0
  142. package/dist/validate-memory-size.d.ts +1 -0
  143. package/dist/validate-memory-size.js +22 -0
  144. package/dist/validate-presign-expiration.d.ts +1 -0
  145. package/dist/validate-presign-expiration.js +29 -0
  146. package/dist/validate-serveurl.d.ts +1 -0
  147. package/dist/validate-serveurl.js +9 -0
  148. package/dist/validate-webhook-signature.d.ts +5 -0
  149. package/dist/validate-webhook-signature.js +28 -0
  150. package/dist/write-file.d.ts +5 -0
  151. package/dist/write-file.js +56 -0
  152. package/eslint.config.mjs +5 -0
  153. package/package.json +71 -0
  154. package/src/app-router-webhook.ts +64 -0
  155. package/src/apply-lifecycle.ts +30 -0
  156. package/src/aws-clients.ts +60 -0
  157. package/src/aws-provider.ts +135 -0
  158. package/src/bucket-exists.ts +28 -0
  159. package/src/call-lambda-async.ts +39 -0
  160. package/src/call-lambda-streaming.ts +219 -0
  161. package/src/call-lambda-sync.ts +55 -0
  162. package/src/check-credentials.ts +51 -0
  163. package/src/clean-items.ts +47 -0
  164. package/src/constants.ts +38 -0
  165. package/src/content-disposition-header.ts +64 -0
  166. package/src/convert-to-serve-url.ts +24 -0
  167. package/src/create-bucket.ts +67 -0
  168. package/src/delete-file.ts +30 -0
  169. package/src/delete-function.ts +24 -0
  170. package/src/delete-render.ts +107 -0
  171. package/src/encode-aws-url-params.ts +3 -0
  172. package/src/estimate-price.ts +95 -0
  173. package/src/express-webhook.ts +50 -0
  174. package/src/get-account-id.ts +22 -0
  175. package/src/get-aws-client.ts +59 -0
  176. package/src/get-aws-urls.ts +85 -0
  177. package/src/get-buckets.ts +81 -0
  178. package/src/get-compositions-on-lambda.ts +104 -0
  179. package/src/get-credentials.ts +81 -0
  180. package/src/get-env-variable.ts +15 -0
  181. package/src/get-function-name.ts +24 -0
  182. package/src/get-function-version.ts +43 -0
  183. package/src/get-functions.ts +103 -0
  184. package/src/get-output-url-from-metadata.ts +23 -0
  185. package/src/get-render-progress.ts +62 -0
  186. package/src/get-s3-client.ts +22 -0
  187. package/src/get-service-client.ts +178 -0
  188. package/src/get-sites.ts +128 -0
  189. package/src/head-file.ts +28 -0
  190. package/src/index.ts +147 -0
  191. package/src/is-cli.ts +7 -0
  192. package/src/is-flaky-error.ts +101 -0
  193. package/src/is-in-lambda.ts +5 -0
  194. package/src/is-likely-to-have-aws-profile.ts +55 -0
  195. package/src/lambda-version-string.ts +5 -0
  196. package/src/lifecycle-rules.ts +104 -0
  197. package/src/lifecycle.ts +44 -0
  198. package/src/list-objects.ts +83 -0
  199. package/src/make-lambda-payload.ts +317 -0
  200. package/src/make-s3-url.ts +13 -0
  201. package/src/p-limit.ts +75 -0
  202. package/src/pages-router-webhook.ts +58 -0
  203. package/src/parse-function-name.ts +24 -0
  204. package/src/presign-url.ts +110 -0
  205. package/src/price-per-1s.ts +863 -0
  206. package/src/random-hash.ts +10 -0
  207. package/src/read-file.ts +31 -0
  208. package/src/regions.ts +48 -0
  209. package/src/render-media-on-lambda.ts +216 -0
  210. package/src/render-still-on-lambda.ts +195 -0
  211. package/src/runtime-preference.ts +7 -0
  212. package/src/speculate-function-name.ts +27 -0
  213. package/src/test/encode-aws-url.test.ts +7 -0
  214. package/src/test/price-calculation.test.ts +61 -0
  215. package/src/test/pricing.test.ts +32 -0
  216. package/src/test/validate-disk-size-in-mb.test.ts +15 -0
  217. package/src/validate-aws-region.ts +14 -0
  218. package/src/validate-bucketname.ts +24 -0
  219. package/src/validate-disk-size-in-mb.ts +37 -0
  220. package/src/validate-lambda-codec.ts +28 -0
  221. package/src/validate-memory-size.ts +31 -0
  222. package/src/validate-presign-expiration.ts +46 -0
  223. package/src/validate-serveurl.ts +9 -0
  224. package/src/validate-webhook-signature.ts +42 -0
  225. package/src/write-file.ts +74 -0
  226. package/tsconfig.json +9 -0
  227. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,10 @@
1
+ const alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789';
2
+
3
+ export const randomHashImplementation = (): string => {
4
+ return new Array(10)
5
+ .fill(1)
6
+ .map(() => {
7
+ return alphabet[Math.floor(Math.random() * alphabet.length)];
8
+ })
9
+ .join('');
10
+ };
@@ -0,0 +1,31 @@
1
+ import {GetObjectCommand} from '@aws-sdk/client-s3';
2
+ import type {Readable} from 'stream';
3
+ import {getS3Client} from './get-s3-client';
4
+ import type {AwsRegion} from './regions';
5
+
6
+ export const lambdaReadFileImplementation = async ({
7
+ bucketName,
8
+ key,
9
+ region,
10
+ expectedBucketOwner,
11
+ forcePathStyle,
12
+ }: {
13
+ bucketName: string;
14
+ key: string;
15
+ region: AwsRegion;
16
+ expectedBucketOwner: string | null;
17
+ forcePathStyle: boolean;
18
+ }): Promise<Readable> => {
19
+ const {Body} = await getS3Client({
20
+ region,
21
+ customCredentials: null,
22
+ forcePathStyle,
23
+ }).send(
24
+ new GetObjectCommand({
25
+ Bucket: bucketName,
26
+ Key: key,
27
+ ExpectedBucketOwner: expectedBucketOwner ?? undefined,
28
+ }),
29
+ );
30
+ return Body as Readable;
31
+ };
package/src/regions.ts ADDED
@@ -0,0 +1,48 @@
1
+ export const DEFAULT_AWS_REGIONS = [
2
+ 'eu-central-1',
3
+ 'eu-west-1',
4
+ 'eu-west-2',
5
+ 'eu-west-3',
6
+ 'eu-north-1',
7
+ 'us-east-1', // N. Virginia
8
+ 'us-east-2', // Ohio;
9
+ 'us-west-1',
10
+ 'us-west-2', // Oregon
11
+ 'ap-south-1',
12
+ 'ap-southeast-1',
13
+ 'ap-southeast-2',
14
+ 'ap-northeast-1',
15
+ 'ap-northeast-2',
16
+ 'ap-northeast-3',
17
+ 'ca-central-1',
18
+ 'sa-east-1',
19
+ ] as const;
20
+
21
+ export const AWS_REGIONS = [
22
+ 'eu-central-1',
23
+ 'eu-central-2',
24
+ 'eu-west-1',
25
+ 'eu-west-2',
26
+ 'eu-west-3',
27
+ 'eu-south-1',
28
+ 'eu-north-1',
29
+ 'us-east-1', // N. Virginia
30
+ 'us-east-2', // Ohio;
31
+ 'us-west-1',
32
+ 'us-west-2', // Oregon
33
+ 'af-south-1',
34
+ 'ap-south-1',
35
+ 'ap-east-1',
36
+ 'ap-southeast-1',
37
+ 'ap-southeast-2',
38
+ 'ap-northeast-1',
39
+ 'ap-northeast-2',
40
+ 'ap-northeast-3',
41
+ 'ap-southeast-4',
42
+ 'ap-southeast-5',
43
+ 'ca-central-1',
44
+ 'me-south-1',
45
+ 'sa-east-1',
46
+ ] as const;
47
+
48
+ export type AwsRegion = (typeof AWS_REGIONS)[number];
@@ -0,0 +1,216 @@
1
+ import type {
2
+ AudioCodec,
3
+ BrowserSafeApis,
4
+ ChromiumOptions,
5
+ DownloadBehavior,
6
+ FrameRange,
7
+ OutNameInput,
8
+ PixelFormat,
9
+ Privacy,
10
+ ProResProfile,
11
+ ServerlessCodec,
12
+ ToOptions,
13
+ VideoImageFormat,
14
+ WebhookOption,
15
+ } from '@remotion/serverless-client';
16
+ import {
17
+ ServerlessRoutines,
18
+ wrapWithErrorHandling,
19
+ } from '@remotion/serverless-client';
20
+ import {awsImplementation, type AwsProvider} from './aws-provider';
21
+ import {
22
+ getCloudwatchMethodUrl,
23
+ getCloudwatchRendererUrl,
24
+ getLambdaInsightsUrl,
25
+ getProgressJsonUrl,
26
+ getS3RenderUrl,
27
+ } from './get-aws-urls';
28
+ import type {InnerRenderMediaOnLambdaInput} from './make-lambda-payload';
29
+ import {makeLambdaRenderMediaPayload} from './make-lambda-payload';
30
+ import type {AwsRegion} from './regions';
31
+
32
+ export type RenderMediaOnLambdaInput = {
33
+ region: AwsRegion;
34
+ functionName: string;
35
+ serveUrl: string;
36
+ composition: string;
37
+ inputProps?: Record<string, unknown>;
38
+ codec: ServerlessCodec;
39
+ imageFormat?: VideoImageFormat;
40
+ crf?: number | undefined;
41
+ envVariables?: Record<string, string>;
42
+ pixelFormat?: PixelFormat;
43
+ proResProfile?: ProResProfile;
44
+ privacy?: Privacy;
45
+ /**
46
+ * @deprecated Renamed to `jpegQuality`
47
+ */
48
+ quality?: never;
49
+ jpegQuality?: number;
50
+ maxRetries?: number;
51
+ framesPerLambda?: number;
52
+ frameRange?: FrameRange;
53
+ outName?: OutNameInput<AwsProvider>;
54
+ chromiumOptions?: Omit<ChromiumOptions, 'enableMultiProcessOnLinux'>;
55
+ scale?: number;
56
+ everyNthFrame?: number;
57
+ concurrencyPerLambda?: number;
58
+ downloadBehavior?: DownloadBehavior | null;
59
+ overwrite?: boolean;
60
+ webhook?: WebhookOption | null;
61
+ forceWidth?: number | null;
62
+ forceHeight?: number | null;
63
+ rendererFunctionName?: string | null;
64
+ forceBucketName?: string;
65
+ audioCodec?: AudioCodec | null;
66
+ /**
67
+ * @deprecated in favor of `logLevel`: true
68
+ */
69
+ dumpBrowserLogs?: boolean;
70
+ forcePathStyle?: boolean;
71
+ metadata?: Record<string, string> | null;
72
+ } & Partial<ToOptions<typeof BrowserSafeApis.optionsMap.renderMediaOnLambda>>;
73
+
74
+ export type RenderMediaOnLambdaOutput = {
75
+ renderId: string;
76
+ bucketName: string;
77
+ cloudWatchLogs: string;
78
+ cloudWatchMainLogs: string;
79
+ lambdaInsightsLogs: string;
80
+ folderInS3Console: string;
81
+ progressJsonInConsole: string;
82
+ };
83
+
84
+ export const internalRenderMediaOnLambdaRaw = async (
85
+ input: InnerRenderMediaOnLambdaInput,
86
+ ): Promise<RenderMediaOnLambdaOutput> => {
87
+ const {functionName, region, rendererFunctionName} = input;
88
+
89
+ try {
90
+ const res = await awsImplementation.callFunctionSync({
91
+ functionName,
92
+ type: ServerlessRoutines.start,
93
+ payload: await makeLambdaRenderMediaPayload(input),
94
+ region,
95
+ timeoutInTest: 120000,
96
+ });
97
+
98
+ return {
99
+ renderId: res.renderId,
100
+ bucketName: res.bucketName,
101
+ cloudWatchLogs: getCloudwatchRendererUrl({
102
+ functionName,
103
+ region,
104
+ renderId: res.renderId,
105
+ rendererFunctionName: rendererFunctionName ?? null,
106
+ chunk: null,
107
+ }),
108
+ cloudWatchMainLogs: getCloudwatchMethodUrl({
109
+ renderId: res.renderId,
110
+ functionName,
111
+ method: ServerlessRoutines.launch,
112
+ region,
113
+ rendererFunctionName: rendererFunctionName ?? null,
114
+ }),
115
+ folderInS3Console: getS3RenderUrl({
116
+ bucketName: res.bucketName,
117
+ renderId: res.renderId,
118
+ region,
119
+ }),
120
+ lambdaInsightsLogs: getLambdaInsightsUrl({
121
+ functionName,
122
+ region,
123
+ }),
124
+ progressJsonInConsole: getProgressJsonUrl({
125
+ bucketName: res.bucketName,
126
+ renderId: res.renderId,
127
+ region,
128
+ }),
129
+ };
130
+ } catch (err) {
131
+ if ((err as Error).stack?.includes('UnrecognizedClientException')) {
132
+ throw new Error(
133
+ 'UnrecognizedClientException: The AWS credentials provided were probably mixed up. Learn how to fix this issue here: https://remotion.dev/docs/lambda/troubleshooting/unrecognizedclientexception',
134
+ );
135
+ }
136
+
137
+ throw err;
138
+ }
139
+ };
140
+
141
+ export const renderMediaOnLambdaOptionalToRequired = (
142
+ options: RenderMediaOnLambdaInput,
143
+ ): InnerRenderMediaOnLambdaInput => {
144
+ return {
145
+ audioBitrate: options.audioBitrate ?? null,
146
+ audioCodec: options.audioCodec ?? null,
147
+ chromiumOptions: options.chromiumOptions ?? {},
148
+ codec: options.codec,
149
+ colorSpace: options.colorSpace ?? null,
150
+ composition: options.composition,
151
+ concurrencyPerLambda: options.concurrencyPerLambda ?? 1,
152
+ crf: options.crf,
153
+ downloadBehavior: options.downloadBehavior ?? {type: 'play-in-browser'},
154
+ envVariables: options.envVariables ?? {},
155
+ everyNthFrame: options.everyNthFrame ?? 1,
156
+ forceBucketName: options.forceBucketName ?? null,
157
+ forceHeight: options.forceHeight ?? null,
158
+ forceWidth: options.forceWidth ?? null,
159
+ frameRange: options.frameRange ?? null,
160
+ framesPerLambda: options.framesPerLambda ?? null,
161
+ functionName: options.functionName,
162
+ imageFormat: options.imageFormat ?? 'jpeg',
163
+ inputProps: options.inputProps ?? {},
164
+ jpegQuality: options.jpegQuality ?? 80,
165
+ logLevel: options.logLevel ?? 'info',
166
+ maxRetries: options.maxRetries ?? 1,
167
+ muted: options.muted ?? false,
168
+ numberOfGifLoops: options.numberOfGifLoops ?? null,
169
+ offthreadVideoCacheSizeInBytes:
170
+ options.offthreadVideoCacheSizeInBytes ?? null,
171
+ outName: options.outName ?? null,
172
+ overwrite: options.overwrite ?? false,
173
+ pixelFormat: options.pixelFormat ?? undefined,
174
+ privacy: options.privacy ?? 'public',
175
+ proResProfile: options.proResProfile ?? undefined,
176
+ region: options.region,
177
+ rendererFunctionName: options.rendererFunctionName ?? null,
178
+ scale: options.scale ?? 1,
179
+ serveUrl: options.serveUrl,
180
+ timeoutInMilliseconds: options.timeoutInMilliseconds ?? 30000,
181
+ videoBitrate: options.videoBitrate ?? null,
182
+ encodingMaxRate: options.encodingMaxRate ?? null,
183
+ encodingBufferSize: options.encodingBufferSize ?? null,
184
+ webhook: options.webhook ?? null,
185
+ x264Preset: options.x264Preset ?? null,
186
+ deleteAfter: options.deleteAfter ?? null,
187
+ preferLossless: options.preferLossless ?? false,
188
+ forcePathStyle: options.forcePathStyle ?? false,
189
+ indent: false,
190
+ metadata: options.metadata ?? null,
191
+ apiKey: options.apiKey ?? null,
192
+ };
193
+ };
194
+
195
+ const wrapped = wrapWithErrorHandling(internalRenderMediaOnLambdaRaw);
196
+
197
+ /*
198
+ * @description Kicks off a render process on Remotion Lambda. The progress can be tracked using getRenderProgress().
199
+ * @see [Documentation](https://remotion.dev/docs/lambda/rendermediaonlambda)
200
+ */
201
+ export const renderMediaOnLambda = (
202
+ options: RenderMediaOnLambdaInput,
203
+ ): Promise<RenderMediaOnLambdaOutput> => {
204
+ if (options.quality) {
205
+ throw new Error(
206
+ 'quality has been renamed to jpegQuality. Please rename the option.',
207
+ );
208
+ }
209
+
210
+ return wrapped(renderMediaOnLambdaOptionalToRequired(options));
211
+ };
212
+
213
+ /**
214
+ * @deprecated Renamed to renderMediaOnLambda()
215
+ */
216
+ export const renderVideoOnLambda = renderMediaOnLambda;
@@ -0,0 +1,195 @@
1
+ import type {
2
+ BrowserSafeApis,
3
+ ChromiumOptions,
4
+ DownloadBehavior,
5
+ StillImageFormat,
6
+ ToOptions,
7
+ } from '@remotion/serverless-client';
8
+ import {ServerlessRoutines} from '@remotion/serverless-client';
9
+
10
+ import type {
11
+ CostsInfo,
12
+ OutNameInput,
13
+ Privacy,
14
+ ReceivedArtifact,
15
+ RenderStillFunctionResponsePayload,
16
+ } from '@remotion/serverless-client';
17
+ import {wrapWithErrorHandling} from '@remotion/serverless-client';
18
+ import {awsImplementation, type AwsProvider} from './aws-provider';
19
+ import {DEFAULT_MAX_RETRIES} from './constants';
20
+ import {getCloudwatchMethodUrl, getLambdaInsightsUrl} from './get-aws-urls';
21
+ import {makeLambdaRenderStillPayload} from './make-lambda-payload';
22
+ import type {AwsRegion} from './regions';
23
+
24
+ type MandatoryParameters = {
25
+ region: AwsRegion;
26
+ functionName: string;
27
+ serveUrl: string;
28
+ composition: string;
29
+ inputProps: Record<string, unknown>;
30
+ imageFormat: StillImageFormat;
31
+ privacy: Privacy;
32
+ };
33
+
34
+ type OptionalParameters = {
35
+ maxRetries: number;
36
+ envVariables: Record<string, string>;
37
+ /**
38
+ * @deprecated Renamed to `jpegQuality`
39
+ */
40
+ quality?: never;
41
+ frame: number;
42
+ outName: OutNameInput<AwsProvider> | null;
43
+ chromiumOptions: ChromiumOptions;
44
+ downloadBehavior: DownloadBehavior;
45
+ forceWidth: number | null;
46
+ forceHeight: number | null;
47
+ forceBucketName: string | null;
48
+ /**
49
+ * @deprecated Renamed to `logLevel`
50
+ */
51
+ dumpBrowserLogs: boolean;
52
+ onInit: (data: {
53
+ renderId: string;
54
+ cloudWatchLogs: string;
55
+ lambdaInsightsUrl: string;
56
+ }) => void;
57
+ indent: boolean;
58
+ forcePathStyle: boolean;
59
+ } & ToOptions<typeof BrowserSafeApis.optionsMap.renderStillOnLambda>;
60
+
61
+ export type RenderStillOnLambdaNonNullInput = MandatoryParameters &
62
+ OptionalParameters;
63
+
64
+ export type RenderStillOnLambdaInput = MandatoryParameters &
65
+ Partial<OptionalParameters>;
66
+
67
+ export type RenderStillOnLambdaOutput = {
68
+ estimatedPrice: CostsInfo;
69
+ url: string;
70
+ outKey: string;
71
+ sizeInBytes: number;
72
+ bucketName: string;
73
+ renderId: string;
74
+ cloudWatchLogs: string;
75
+ artifacts: ReceivedArtifact<AwsProvider>[];
76
+ };
77
+
78
+ const internalRenderStillOnLambda = async (
79
+ input: RenderStillOnLambdaNonNullInput,
80
+ ): Promise<RenderStillOnLambdaOutput> => {
81
+ const {functionName, region, onInit} = input;
82
+ try {
83
+ const payload = await makeLambdaRenderStillPayload(input);
84
+ const res = await new Promise<
85
+ RenderStillFunctionResponsePayload<AwsProvider>
86
+ >((resolve, reject) => {
87
+ awsImplementation
88
+ .callFunctionStreaming<ServerlessRoutines.still>({
89
+ functionName,
90
+ type: ServerlessRoutines.still,
91
+ payload,
92
+ region,
93
+ receivedStreamingPayload: ({message}) => {
94
+ if (message.type === 'render-id-determined') {
95
+ onInit?.({
96
+ renderId: message.payload.renderId,
97
+ cloudWatchLogs: getCloudwatchMethodUrl({
98
+ functionName,
99
+ method: ServerlessRoutines.still,
100
+ region,
101
+ rendererFunctionName: null,
102
+ renderId: message.payload.renderId,
103
+ }),
104
+ lambdaInsightsUrl: getLambdaInsightsUrl({
105
+ functionName,
106
+ region,
107
+ }),
108
+ });
109
+ }
110
+
111
+ if (message.type === 'error-occurred') {
112
+ reject(new Error(message.payload.error));
113
+ }
114
+
115
+ if (message.type === 'still-rendered') {
116
+ resolve(message.payload);
117
+ }
118
+ },
119
+ timeoutInTest: 120000,
120
+ retriesRemaining: input.maxRetries,
121
+ })
122
+ .then(() => {
123
+ reject(new Error('Expected response to be streamed'));
124
+ })
125
+ .catch((err) => {
126
+ reject(err);
127
+ });
128
+ });
129
+
130
+ return {
131
+ estimatedPrice: res.estimatedPrice,
132
+ url: res.output,
133
+ outKey: res.outKey,
134
+ sizeInBytes: res.size,
135
+ bucketName: res.bucketName,
136
+ renderId: res.renderId,
137
+ cloudWatchLogs: getCloudwatchMethodUrl({
138
+ functionName,
139
+ method: ServerlessRoutines.still,
140
+ region,
141
+ renderId: res.renderId,
142
+ rendererFunctionName: null,
143
+ }),
144
+ artifacts: res.receivedArtifacts,
145
+ };
146
+ } catch (err) {
147
+ if ((err as Error).stack?.includes('UnrecognizedClientException')) {
148
+ throw new Error(
149
+ 'UnrecognizedClientException: The AWS credentials provided were probably mixed up. Learn how to fix this issue here: https://remotion.dev/docs/lambda/troubleshooting/unrecognizedclientexception',
150
+ );
151
+ }
152
+
153
+ throw err;
154
+ }
155
+ };
156
+
157
+ const errorHandled = wrapWithErrorHandling(internalRenderStillOnLambda);
158
+
159
+ /*
160
+ * @description Renders a still image inside a lambda function and writes it to the specified output location.
161
+ * @see [Documentation](https://remotion.dev/docs/lambda/renderstillonlambda)
162
+ */
163
+ export const renderStillOnLambda = (input: RenderStillOnLambdaInput) => {
164
+ return errorHandled({
165
+ chromiumOptions: input.chromiumOptions ?? {},
166
+ composition: input.composition,
167
+ deleteAfter: input.deleteAfter ?? null,
168
+ downloadBehavior: input.downloadBehavior ?? {type: 'play-in-browser'},
169
+ envVariables: input.envVariables ?? {},
170
+ forceBucketName: input.forceBucketName ?? null,
171
+ forceHeight: input.forceHeight ?? null,
172
+ forceWidth: input.forceWidth ?? null,
173
+ frame: input.frame ?? 0,
174
+ functionName: input.functionName,
175
+ imageFormat: input.imageFormat,
176
+ indent: false,
177
+ inputProps: input.inputProps,
178
+ maxRetries: input.maxRetries ?? DEFAULT_MAX_RETRIES,
179
+ onInit: input.onInit ?? (() => undefined),
180
+ outName: input.outName ?? null,
181
+ privacy: input.privacy,
182
+ quality: undefined,
183
+ region: input.region,
184
+ serveUrl: input.serveUrl,
185
+ jpegQuality: input.jpegQuality ?? 80,
186
+ logLevel: input.dumpBrowserLogs ? 'verbose' : (input.logLevel ?? 'info'),
187
+ offthreadVideoCacheSizeInBytes:
188
+ input.offthreadVideoCacheSizeInBytes ?? null,
189
+ scale: input.scale ?? 1,
190
+ timeoutInMilliseconds: input.timeoutInMilliseconds ?? 30000,
191
+ dumpBrowserLogs: false,
192
+ forcePathStyle: input.forcePathStyle ?? false,
193
+ apiKey: input.apiKey ?? null,
194
+ });
195
+ };
@@ -0,0 +1,7 @@
1
+ export const runtimePreferenceOptions = [
2
+ 'default',
3
+ 'apple-emojis',
4
+ 'cjk',
5
+ ] as const;
6
+
7
+ export type RuntimePreference = (typeof runtimePreferenceOptions)[number];
@@ -0,0 +1,27 @@
1
+ import {RENDER_FN_PREFIX} from './constants';
2
+ import {LAMBDA_VERSION_STRING} from './lambda-version-string';
3
+
4
+ export type SpeculateFunctionNameInput = {
5
+ memorySizeInMb: string | number;
6
+ diskSizeInMb: string | number;
7
+ timeoutInSeconds: string | number;
8
+ };
9
+
10
+ /*
11
+ * @description Speculate the name of the Lambda function that will be created by `deployFunction()` or its CLI equivalent, based on the function configuration.
12
+ * @see [Documentation](https://remotion.dev/docs/lambda/speculatefunctionname)
13
+ */
14
+ export const speculateFunctionName = ({
15
+ memorySizeInMb,
16
+ diskSizeInMb,
17
+ timeoutInSeconds,
18
+ }: SpeculateFunctionNameInput) => {
19
+ // find-function-name.ts uses this for templating
20
+ // consider this before adding any validation here
21
+ return [
22
+ `${RENDER_FN_PREFIX}${LAMBDA_VERSION_STRING}`,
23
+ `mem${memorySizeInMb}mb`,
24
+ `disk${diskSizeInMb}mb`,
25
+ `${timeoutInSeconds}sec`,
26
+ ].join('-');
27
+ };
@@ -0,0 +1,7 @@
1
+ import {expect, test} from 'bun:test';
2
+ import {encodeAwsUrlParams} from '../encode-aws-url-params';
3
+
4
+ test('Encode AWS URL test', () => {
5
+ const params = encodeAwsUrlParams('"method=test"');
6
+ expect(params).toBe('$2522method$253Dtest$2522');
7
+ });
@@ -0,0 +1,61 @@
1
+ import {estimatePriceFromMetadata} from '@remotion/serverless-client';
2
+ import {expect, test} from 'bun:test';
3
+ import {awsImplementation} from '../aws-provider';
4
+
5
+ test('Should not throw while calculating prices when time shifts occur', () => {
6
+ const aDate = Date.now();
7
+ process.env.AWS_REGION = 'us-east-1';
8
+
9
+ const price = estimatePriceFromMetadata({
10
+ memorySizeInMb: 1024,
11
+ renderMetadata: {
12
+ audioBitrate: null,
13
+ codec: 'h264',
14
+ compositionId: 'react-svg',
15
+ estimatedRenderLambdaInvokations: 10,
16
+ estimatedTotalLambdaInvokations: 10,
17
+ framesPerLambda: 10,
18
+ imageFormat: 'jpeg',
19
+ inputProps: {
20
+ type: 'payload',
21
+ payload: '{}',
22
+ },
23
+ lambdaVersion: '2021-11-29',
24
+ memorySizeInMb: 1024,
25
+ region: 'eu-central-1',
26
+ renderId: '123',
27
+ deleteAfter: null,
28
+ siteId: 'my-site',
29
+ startedDate: aDate + 1000,
30
+ totalChunks: 20,
31
+ type: 'video',
32
+ outName: 'out.mp4',
33
+ privacy: 'public',
34
+ everyNthFrame: 1,
35
+ frameRange: [0, 99],
36
+ audioCodec: null,
37
+ downloadBehavior: {type: 'play-in-browser'},
38
+ numberOfGifLoops: null,
39
+ muted: false,
40
+ metadata: {Author: 'Lunar'},
41
+ functionName: 'remotion-render-la8ffw',
42
+ rendererFunctionName: 'remotion-render-la8ffw',
43
+ dimensions: {
44
+ height: 1080,
45
+ width: 1920,
46
+ },
47
+ },
48
+ diskSizeInMb: 512,
49
+ functionsInvoked: 1,
50
+ timings: [
51
+ {
52
+ chunk: 1,
53
+ rendered: aDate - 2000,
54
+ start: aDate,
55
+ },
56
+ ],
57
+ region: 'eu-central-1',
58
+ providerSpecifics: awsImplementation,
59
+ });
60
+ expect(price?.accruedSoFar).toBeGreaterThanOrEqual(0);
61
+ });
@@ -0,0 +1,32 @@
1
+ import {expect, test} from 'bun:test';
2
+ import {estimatePrice} from '../estimate-price';
3
+
4
+ test('Should calculate costs accurately', () => {
5
+ expect(
6
+ estimatePrice({
7
+ region: 'us-east-1',
8
+ durationInMiliseconds: 20000000,
9
+ memorySizeInMb: 2048,
10
+ diskSizeInMb: 512,
11
+ lambdasInvoked: 1,
12
+ }),
13
+ ).toEqual(0.53334);
14
+ expect(
15
+ estimatePrice({
16
+ region: 'us-east-1',
17
+ durationInMilliseconds: 20000000,
18
+ memorySizeInMb: 2048,
19
+ diskSizeInMb: 10240,
20
+ lambdasInvoked: 1,
21
+ }),
22
+ ).toEqual(0.53921);
23
+ expect(
24
+ estimatePrice({
25
+ region: 'us-east-1',
26
+ durationInMiliseconds: 20000000,
27
+ memorySizeInMb: 2048,
28
+ diskSizeInMb: 10240,
29
+ lambdasInvoked: 1,
30
+ }),
31
+ ).toEqual(0.53921);
32
+ });
@@ -0,0 +1,15 @@
1
+ import {expect, test} from 'bun:test';
2
+ import {validateDiskSizeInMb} from '../validate-disk-size-in-mb';
3
+
4
+ test('Disk size tests', () => {
5
+ expect(() => validateDiskSizeInMb(512)).not.toThrow();
6
+ expect(() => validateDiskSizeInMb(10240)).not.toThrow();
7
+ expect(() => {
8
+ validateDiskSizeInMb(0);
9
+ }).toThrow(
10
+ /parameter 'diskSizeInMb' must be between 512 and 10240, but got 0/,
11
+ );
12
+ expect(() => {
13
+ validateDiskSizeInMb({});
14
+ }).toThrow(/parameter 'diskSizeInMb' must be a number, got a object/);
15
+ });
@@ -0,0 +1,14 @@
1
+ import type {AwsRegion} from './regions';
2
+ import {AWS_REGIONS} from './regions';
3
+
4
+ export function validateAwsRegion(
5
+ region: unknown,
6
+ ): asserts region is AwsRegion {
7
+ if (!AWS_REGIONS.includes(region as AwsRegion)) {
8
+ throw new TypeError(
9
+ `${region} is not a supported AWS region. Must be one of: ${AWS_REGIONS.join(
10
+ ', ',
11
+ )}`,
12
+ );
13
+ }
14
+ }
@@ -0,0 +1,24 @@
1
+ import {REMOTION_BUCKET_PREFIX} from './constants';
2
+ import type {AwsRegion} from './regions';
3
+ import {AWS_REGIONS} from './regions';
4
+
5
+ export const parseBucketName = (
6
+ name: string,
7
+ ): {
8
+ region: AwsRegion | null;
9
+ } => {
10
+ const parsed = name.match(
11
+ new RegExp(`^${REMOTION_BUCKET_PREFIX}(.*)-([a-z0-9A-Z]+)$`),
12
+ );
13
+ const region = parsed?.[1] as AwsRegion;
14
+
15
+ if (!region) {
16
+ return {region: null};
17
+ }
18
+
19
+ const realRegionFound = AWS_REGIONS.find(
20
+ (r) => r.replace(/-/g, '') === region,
21
+ );
22
+
23
+ return {region: realRegionFound ?? null};
24
+ };