@remotion/cloudrun 4.0.21 → 4.0.23

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.
@@ -1,13 +1,13 @@
1
1
 
2
- > @remotion/cloudrun@4.0.20 build /Users/jonathanburger/remotion/packages/cloudrun
2
+ > @remotion/cloudrun@4.0.22 build /Users/jonathanburger/remotion-v4/packages/cloudrun
3
3
  > tsc -d && cp src/shared/sa-permissions.json dist/shared/sa-permissions.json && pnpm run buildContainer && pnpm run tarInstaller
4
4
 
5
5
 
6
- > @remotion/cloudrun@4.0.20 buildContainer /Users/jonathanburger/remotion/packages/cloudrun
6
+ > @remotion/cloudrun@4.0.22 buildContainer /Users/jonathanburger/remotion-v4/packages/cloudrun
7
7
  > ts-node src/admin/bundle-renderLogic.ts
8
8
 
9
9
  distribution bundled.
10
10
 
11
- > @remotion/cloudrun@4.0.20 tarInstaller /Users/jonathanburger/remotion/packages/cloudrun
11
+ > @remotion/cloudrun@4.0.22 tarInstaller /Users/jonathanburger/remotion-v4/packages/cloudrun
12
12
  > ts-node src/admin/bundle-installer.ts
13
13
 
@@ -1,4 +1,5 @@
1
- import type { AudioCodec, ChromiumOptions, FrameRange, LogLevel, PixelFormat, ProResProfile, VideoImageFormat } from '@remotion/renderer';
1
+ import type { AudioCodec, ChromiumOptions, FrameRange, LogLevel, PixelFormat, ProResProfile, ToOptions, VideoImageFormat, X264Preset } from '@remotion/renderer';
2
+ import type { BrowserSafeApis } from '@remotion/renderer/client';
2
3
  import type { CloudRunCrashResponse, RenderMediaOnCloudrunOutput } from '../functions/helpers/payloads';
3
4
  import type { GcpRegion } from '../pricing/gcp-regions';
4
5
  import type { CloudrunCodec } from '../shared/validate-gcp-codec';
@@ -19,6 +20,7 @@ export type RenderMediaOnCloudrunInput = {
19
20
  audioBitrate?: string | null;
20
21
  videoBitrate?: string | null;
21
22
  proResProfile?: ProResProfile;
23
+ x264Preset?: X264Preset;
22
24
  crf?: number | undefined;
23
25
  pixelFormat?: PixelFormat;
24
26
  imageFormat?: VideoImageFormat;
@@ -36,7 +38,7 @@ export type RenderMediaOnCloudrunInput = {
36
38
  concurrency?: number | string | null;
37
39
  enforceAudioTrack?: boolean;
38
40
  preferLossless?: boolean;
39
- };
41
+ } & Partial<ToOptions<typeof BrowserSafeApis.optionsMap.renderMediaOnLambda>>;
40
42
  /**
41
43
  * @description Triggers a render on a GCP Cloud Run service given a composition and a Cloud Run URL.
42
44
  * @see [Documentation](https://remotion.dev/docs/cloudrun/renderMediaOnGcp)
@@ -56,6 +58,7 @@ export type RenderMediaOnCloudrunInput = {
56
58
  * @param params.audioBitrate The target bitrate for the audio of the generated video.
57
59
  * @param params.videoBitrate The target bitrate of the generated video.
58
60
  * @param params.proResProfile Sets a ProRes profile. Only applies to videos rendered with prores codec.
61
+ * @param params.x264Preset Sets a Preset profile. Only applies to videos rendered with h.264 codec.
59
62
  * @param params.crf Constant Rate Factor, controlling the quality.
60
63
  * @param params.pixelFormat Custom pixel format to use. Usually used for special use cases like transparent videos.
61
64
  * @param params.imageFormat Which image format the frames should be rendered in.
@@ -75,4 +78,4 @@ export type RenderMediaOnCloudrunInput = {
75
78
  * @param params.preferLossless Uses a lossless audio codec, if one is available for the codec. If you set audioCodec, it takes priority over preferLossless.
76
79
  * @returns {Promise<RenderMediaOnCloudrunOutput>} See documentation for detailed structure
77
80
  */
78
- export declare const renderMediaOnCloudrun: ({ cloudRunUrl, serviceName, region, serveUrl, composition, inputProps, codec, forceBucketName, privacy, outName, updateRenderProgress, jpegQuality, audioCodec, audioBitrate, videoBitrate, proResProfile, crf, pixelFormat, imageFormat, scale, everyNthFrame, numberOfGifLoops, frameRange, envVariables, chromiumOptions, muted, forceWidth, forceHeight, logLevel, delayRenderTimeoutInMilliseconds, concurrency, enforceAudioTrack, preferLossless, }: RenderMediaOnCloudrunInput) => Promise<RenderMediaOnCloudrunOutput | CloudRunCrashResponse>;
81
+ export declare const renderMediaOnCloudrun: ({ cloudRunUrl, serviceName, region, serveUrl, composition, inputProps, codec, forceBucketName, privacy, outName, updateRenderProgress, jpegQuality, audioCodec, audioBitrate, videoBitrate, proResProfile, x264Preset, crf, pixelFormat, imageFormat, scale, everyNthFrame, numberOfGifLoops, frameRange, envVariables, chromiumOptions, muted, forceWidth, forceHeight, logLevel, delayRenderTimeoutInMilliseconds, concurrency, enforceAudioTrack, preferLossless, offthreadVideoCacheSizeInBytes, }: RenderMediaOnCloudrunInput) => Promise<RenderMediaOnCloudrunOutput | CloudRunCrashResponse>;
@@ -28,6 +28,7 @@ const get_cloudrun_endpoint_1 = require("./helpers/get-cloudrun-endpoint");
28
28
  * @param params.audioBitrate The target bitrate for the audio of the generated video.
29
29
  * @param params.videoBitrate The target bitrate of the generated video.
30
30
  * @param params.proResProfile Sets a ProRes profile. Only applies to videos rendered with prores codec.
31
+ * @param params.x264Preset Sets a Preset profile. Only applies to videos rendered with h.264 codec.
31
32
  * @param params.crf Constant Rate Factor, controlling the quality.
32
33
  * @param params.pixelFormat Custom pixel format to use. Usually used for special use cases like transparent videos.
33
34
  * @param params.imageFormat Which image format the frames should be rendered in.
@@ -47,7 +48,7 @@ const get_cloudrun_endpoint_1 = require("./helpers/get-cloudrun-endpoint");
47
48
  * @param params.preferLossless Uses a lossless audio codec, if one is available for the codec. If you set audioCodec, it takes priority over preferLossless.
48
49
  * @returns {Promise<RenderMediaOnCloudrunOutput>} See documentation for detailed structure
49
50
  */
50
- const renderMediaOnCloudrun = async ({ cloudRunUrl, serviceName, region, serveUrl, composition, inputProps, codec, forceBucketName, privacy, outName, updateRenderProgress, jpegQuality, audioCodec, audioBitrate, videoBitrate, proResProfile, crf, pixelFormat, imageFormat, scale, everyNthFrame, numberOfGifLoops, frameRange, envVariables, chromiumOptions, muted, forceWidth, forceHeight, logLevel, delayRenderTimeoutInMilliseconds, concurrency, enforceAudioTrack, preferLossless, }) => {
51
+ const renderMediaOnCloudrun = async ({ cloudRunUrl, serviceName, region, serveUrl, composition, inputProps, codec, forceBucketName, privacy, outName, updateRenderProgress, jpegQuality, audioCodec, audioBitrate, videoBitrate, proResProfile, x264Preset, crf, pixelFormat, imageFormat, scale, everyNthFrame, numberOfGifLoops, frameRange, envVariables, chromiumOptions, muted, forceWidth, forceHeight, logLevel, delayRenderTimeoutInMilliseconds, concurrency, enforceAudioTrack, preferLossless, offthreadVideoCacheSizeInBytes, }) => {
51
52
  const actualCodec = (0, validate_gcp_codec_1.validateCloudrunCodec)(codec);
52
53
  (0, validate_serveurl_1.validateServeUrl)(serveUrl);
53
54
  if (privacy)
@@ -76,6 +77,7 @@ const renderMediaOnCloudrun = async ({ cloudRunUrl, serviceName, region, serveUr
76
77
  imageFormat: imageFormat !== null && imageFormat !== void 0 ? imageFormat : renderer_1.RenderInternals.DEFAULT_VIDEO_IMAGE_FORMAT,
77
78
  scale: scale !== null && scale !== void 0 ? scale : 1,
78
79
  proResProfile: proResProfile !== null && proResProfile !== void 0 ? proResProfile : null,
80
+ x264Preset: x264Preset !== null && x264Preset !== void 0 ? x264Preset : null,
79
81
  everyNthFrame: everyNthFrame !== null && everyNthFrame !== void 0 ? everyNthFrame : 1,
80
82
  numberOfGifLoops: numberOfGifLoops !== null && numberOfGifLoops !== void 0 ? numberOfGifLoops : null,
81
83
  frameRange: frameRange !== null && frameRange !== void 0 ? frameRange : null,
@@ -93,6 +95,7 @@ const renderMediaOnCloudrun = async ({ cloudRunUrl, serviceName, region, serveUr
93
95
  concurrency: concurrency !== null && concurrency !== void 0 ? concurrency : null,
94
96
  enforceAudioTrack: enforceAudioTrack !== null && enforceAudioTrack !== void 0 ? enforceAudioTrack : false,
95
97
  preferLossless: preferLossless !== null && preferLossless !== void 0 ? preferLossless : false,
98
+ offthreadVideoCacheSizeInBytes: offthreadVideoCacheSizeInBytes !== null && offthreadVideoCacheSizeInBytes !== void 0 ? offthreadVideoCacheSizeInBytes : null,
96
99
  };
97
100
  const client = await (0, get_auth_client_for_url_1.getAuthClientForUrl)(cloudRunEndpoint);
98
101
  const postResponse = await client.request({
@@ -107,13 +110,27 @@ const renderMediaOnCloudrun = async ({ cloudRunUrl, serviceName, region, serveUr
107
110
  const startTime = Date.now();
108
111
  const formattedStartTime = new Date().toISOString();
109
112
  const stream = postResponse.data;
113
+ let accumulatedChunks = ''; // A buffer to accumulate chunks.
110
114
  stream.on('data', (chunk) => {
111
- const chunkResponse = JSON.parse(chunk.toString().trim());
112
- if (chunkResponse.response) {
113
- response = chunkResponse.response;
115
+ accumulatedChunks += chunk.toString(); // Add the new chunk to the buffer.
116
+ let parsedData;
117
+ try {
118
+ parsedData = JSON.parse(accumulatedChunks.trim());
119
+ accumulatedChunks = ''; // Clear the buffer after successful parsing.
114
120
  }
115
- else if (chunkResponse.onProgress) {
116
- updateRenderProgress === null || updateRenderProgress === void 0 ? void 0 : updateRenderProgress(chunkResponse.onProgress);
121
+ catch (e) {
122
+ // If parsing fails, it means we don't have a complete JSON string yet.
123
+ // We'll wait for more chunks.
124
+ return;
125
+ }
126
+ if (parsedData.response) {
127
+ response = parsedData.response;
128
+ }
129
+ else if (parsedData.onProgress) {
130
+ updateRenderProgress === null || updateRenderProgress === void 0 ? void 0 : updateRenderProgress(parsedData.onProgress);
131
+ }
132
+ if (parsedData.type === 'error') {
133
+ reject(parsedData);
117
134
  }
118
135
  });
119
136
  stream.on('end', () => {
@@ -122,7 +139,7 @@ const renderMediaOnCloudrun = async ({ cloudRunUrl, serviceName, region, serveUr
122
139
  const formattedCrashTime = new Date().toISOString();
123
140
  updateRenderProgress === null || updateRenderProgress === void 0 ? void 0 : updateRenderProgress(0, true);
124
141
  resolve({
125
- status: 'crash',
142
+ type: 'crash',
126
143
  cloudRunEndpoint,
127
144
  message: 'Service crashed without sending a response. Check the logs in GCP console.',
128
145
  requestStartTime: formattedStartTime,
@@ -130,8 +147,8 @@ const renderMediaOnCloudrun = async ({ cloudRunUrl, serviceName, region, serveUr
130
147
  requestElapsedTimeInSeconds: (crashTime - startTime) / 1000,
131
148
  });
132
149
  }
133
- else if (response.status !== 'success' && response.status !== 'crash') {
134
- throw new Error(response.stack);
150
+ else if (response.type !== 'success' && response.type !== 'crash') {
151
+ throw response;
135
152
  }
136
153
  resolve(response);
137
154
  });
@@ -1,5 +1,6 @@
1
- import type { ChromiumOptions, LogLevel, StillImageFormat } from '@remotion/renderer';
2
- import type { RenderStillOnCloudrunOutput } from '../functions/helpers/payloads';
1
+ import type { ChromiumOptions, LogLevel, StillImageFormat, ToOptions } from '@remotion/renderer';
2
+ import type { BrowserSafeApis } from '@remotion/renderer/client';
3
+ import type { CloudRunCrashResponse, ErrorResponsePayload, RenderStillOnCloudrunOutput } from '../functions/helpers/payloads';
3
4
  import type { GcpRegion } from '../pricing/gcp-regions';
4
5
  export type RenderStillOnCloudrunInput = {
5
6
  cloudRunUrl?: string;
@@ -21,7 +22,7 @@ export type RenderStillOnCloudrunInput = {
21
22
  forceHeight?: number | null;
22
23
  logLevel?: LogLevel;
23
24
  delayRenderTimeoutInMilliseconds?: number;
24
- };
25
+ } & Partial<ToOptions<typeof BrowserSafeApis.optionsMap.renderMediaOnLambda>>;
25
26
  /**
26
27
  * @description Triggers a render on a GCP Cloud Run service given a composition and a Cloud Run URL.
27
28
  * @see [Documentation](https://remotion.dev/docs/cloudrun/renderstilloncloudrun)
@@ -46,4 +47,4 @@ export type RenderStillOnCloudrunInput = {
46
47
  * @param params.delayRenderTimeoutInMilliseconds A number describing how long the render may take to resolve all delayRender() calls before it times out.
47
48
  * @returns {Promise<RenderStillOnCloudrunOutput>} See documentation for detailed structure
48
49
  */
49
- export declare const renderStillOnCloudrun: ({ cloudRunUrl, serviceName, region, serveUrl, composition, inputProps, forceBucketName, privacy, outName, imageFormat, envVariables, frame, jpegQuality, chromiumOptions, scale, forceWidth, forceHeight, logLevel, delayRenderTimeoutInMilliseconds, }: RenderStillOnCloudrunInput) => Promise<RenderStillOnCloudrunOutput>;
50
+ export declare const renderStillOnCloudrun: ({ cloudRunUrl, serviceName, region, serveUrl, composition, inputProps, forceBucketName, privacy, outName, imageFormat, envVariables, frame, jpegQuality, chromiumOptions, scale, forceWidth, forceHeight, logLevel, delayRenderTimeoutInMilliseconds, offthreadVideoCacheSizeInBytes, }: RenderStillOnCloudrunInput) => Promise<RenderStillOnCloudrunOutput | ErrorResponsePayload | CloudRunCrashResponse>;
@@ -32,7 +32,7 @@ const get_cloudrun_endpoint_1 = require("./helpers/get-cloudrun-endpoint");
32
32
  * @param params.delayRenderTimeoutInMilliseconds A number describing how long the render may take to resolve all delayRender() calls before it times out.
33
33
  * @returns {Promise<RenderStillOnCloudrunOutput>} See documentation for detailed structure
34
34
  */
35
- const renderStillOnCloudrun = async ({ cloudRunUrl, serviceName, region, serveUrl, composition, inputProps, forceBucketName, privacy, outName, imageFormat, envVariables, frame, jpegQuality, chromiumOptions, scale, forceWidth, forceHeight, logLevel, delayRenderTimeoutInMilliseconds, }) => {
35
+ const renderStillOnCloudrun = async ({ cloudRunUrl, serviceName, region, serveUrl, composition, inputProps, forceBucketName, privacy, outName, imageFormat, envVariables, frame, jpegQuality, chromiumOptions, scale, forceWidth, forceHeight, logLevel, delayRenderTimeoutInMilliseconds, offthreadVideoCacheSizeInBytes, }) => {
36
36
  (0, validate_serveurl_1.validateServeUrl)(serveUrl);
37
37
  if (privacy)
38
38
  (0, validate_privacy_1.validatePrivacy)(privacy);
@@ -64,13 +64,62 @@ const renderStillOnCloudrun = async ({ cloudRunUrl, serviceName, region, serveUr
64
64
  type: 'still',
65
65
  logLevel: logLevel !== null && logLevel !== void 0 ? logLevel : 'info',
66
66
  delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds !== null && delayRenderTimeoutInMilliseconds !== void 0 ? delayRenderTimeoutInMilliseconds : renderer_1.RenderInternals.DEFAULT_TIMEOUT,
67
+ offthreadVideoCacheSizeInBytes: offthreadVideoCacheSizeInBytes !== null && offthreadVideoCacheSizeInBytes !== void 0 ? offthreadVideoCacheSizeInBytes : null,
67
68
  };
68
69
  const client = await (0, get_auth_client_for_url_1.getAuthClientForUrl)(cloudRunEndpoint);
69
- const renderResponse = await client.request({
70
+ const postResponse = await client.request({
70
71
  url: cloudRunUrl,
71
72
  method: 'POST',
72
73
  data,
74
+ responseType: 'stream',
73
75
  });
74
- return renderResponse.data;
76
+ const renderResponse = await new Promise((resolve, reject) => {
77
+ let response;
78
+ const startTime = Date.now();
79
+ const formattedStartTime = new Date().toISOString();
80
+ const stream = postResponse.data;
81
+ let accumulatedChunks = ''; // A buffer to accumulate chunks.
82
+ stream.on('data', (chunk) => {
83
+ accumulatedChunks += chunk.toString(); // Add the new chunk to the buffer.
84
+ let parsedData;
85
+ try {
86
+ parsedData = JSON.parse(accumulatedChunks.trim());
87
+ accumulatedChunks = ''; // Clear the buffer after successful parsing.
88
+ }
89
+ catch (e) {
90
+ // If parsing fails, it means we don't have a complete JSON string yet.
91
+ // We'll wait for more chunks.
92
+ return;
93
+ }
94
+ if (parsedData.response) {
95
+ response = parsedData.response;
96
+ }
97
+ if (parsedData.type === 'error') {
98
+ reject(parsedData);
99
+ }
100
+ });
101
+ stream.on('end', () => {
102
+ if (!response) {
103
+ const crashTime = Date.now();
104
+ const formattedCrashTime = new Date().toISOString();
105
+ resolve({
106
+ type: 'crash',
107
+ cloudRunEndpoint,
108
+ message: 'Service crashed without sending a response. Check the logs in GCP console.',
109
+ requestStartTime: formattedStartTime,
110
+ requestCrashTime: formattedCrashTime,
111
+ requestElapsedTimeInSeconds: (crashTime - startTime) / 1000,
112
+ });
113
+ }
114
+ else if (response.type !== 'success' && response.type !== 'crash') {
115
+ throw response;
116
+ }
117
+ resolve(response);
118
+ });
119
+ stream.on('error', (error) => {
120
+ reject(error);
121
+ });
122
+ });
123
+ return renderResponse;
75
124
  };
76
125
  exports.renderStillOnCloudrun = renderStillOnCloudrun;
@@ -6,12 +6,10 @@ const config_1 = require("@remotion/cli/config");
6
6
  const renderer_1 = require("@remotion/renderer");
7
7
  const remotion_1 = require("remotion");
8
8
  const download_file_1 = require("../../../api/download-file");
9
- const extract_mem_from_url_1 = require("../../../api/helpers/extract-mem-from-url");
10
- const extract_time_from_url_1 = require("../../../api/helpers/extract-time-from-url");
11
- const get_cloud_logging_client_1 = require("../../../api/helpers/get-cloud-logging-client");
12
9
  const render_media_on_cloudrun_1 = require("../../../api/render-media-on-cloudrun");
13
10
  const validate_serveurl_1 = require("../../../shared/validate-serveurl");
14
11
  const args_1 = require("../../args");
12
+ const cloudrun_crash_logs_1 = require("../../helpers/cloudrun-crash-logs");
15
13
  const log_1 = require("../../log");
16
14
  const renderArgsCheck_1 = require("./helpers/renderArgsCheck");
17
15
  exports.RENDER_COMMAND = 'render';
@@ -27,7 +25,7 @@ const renderCommand = async (args, remotionRoot) => {
27
25
  });
28
26
  const imageFormat = args_1.parsedCloudrunCli['image-format'];
29
27
  const audioCodec = args_1.parsedCloudrunCli['audio-codec'];
30
- const { chromiumOptions, crf, envVariables, frameRange, inputProps, logLevel, puppeteerTimeout, pixelFormat, proResProfile, jpegQuality, scale, everyNthFrame, numberOfGifLoops, muted, audioBitrate, videoBitrate, height, width, browserExecutable, port, enforceAudioTrack, } = await cli_1.CliInternals.getCliOptions({
28
+ const { chromiumOptions, crf, envVariables, frameRange, inputProps, logLevel, puppeteerTimeout, pixelFormat, proResProfile, jpegQuality, scale, everyNthFrame, numberOfGifLoops, muted, audioBitrate, videoBitrate, height, width, browserExecutable, port, enforceAudioTrack, offthreadVideoCacheSizeInBytes, } = await cli_1.CliInternals.getCliOptions({
31
29
  type: 'series',
32
30
  isLambda: true,
33
31
  remotionRoot,
@@ -46,6 +44,7 @@ const renderCommand = async (args, remotionRoot) => {
46
44
  remotionRoot,
47
45
  logLevel,
48
46
  webpackConfigOrServeUrl: serveUrl,
47
+ offthreadVideoCacheSizeInBytes: offthreadVideoCacheSizeInBytes !== null && offthreadVideoCacheSizeInBytes !== void 0 ? offthreadVideoCacheSizeInBytes : null,
49
48
  });
50
49
  const { compositionId } = await cli_1.CliInternals.getCompositionWithDimensionOverride({
51
50
  args: args.slice(1),
@@ -67,6 +66,7 @@ const renderCommand = async (args, remotionRoot) => {
67
66
  indent: undefined,
68
67
  staticBase: null,
69
68
  }).serializedString,
69
+ offthreadVideoCacheSizeInBytes,
70
70
  });
71
71
  composition = compositionId;
72
72
  }
@@ -152,55 +152,10 @@ ${downloadName ? ` Downloaded File = ${downloadName}` : ''}
152
152
  enforceAudioTrack,
153
153
  preferLossless: false,
154
154
  });
155
- if (res.status === 'crash') {
156
- let timeoutPreMsg = '';
157
- const timeout = (0, extract_time_from_url_1.extractTimeoutFromURL)(res.cloudRunEndpoint);
158
- const memoryLimit = (0, extract_mem_from_url_1.extractMemoryFromURL)(res.cloudRunEndpoint);
159
- if (timeout && res.requestElapsedTimeInSeconds + 10 > timeout) {
160
- timeoutPreMsg = `Render call likely timed out. Service timeout is ${timeout} seconds, and render took at least ${res.requestElapsedTimeInSeconds.toFixed(1)} seconds.\n`;
161
- }
162
- else {
163
- timeoutPreMsg = `Crash unlikely due to timeout. Render took ${res.requestElapsedTimeInSeconds.toFixed(1)} seconds, below the timeout of ${timeout} seconds.\n`;
164
- }
165
- log_1.Log.error(`Error rendering on Cloud Run. The Cloud Run service did not return a response.\n
166
- ${timeoutPreMsg}The crash may be due to the service exceeding its memory limit of ${memoryLimit}.
167
- Full logs are available at https://console.cloud.google.com/run?project=${process.env.REMOTION_GCP_PROJECT_ID}\n`);
168
- const cloudLoggingClient = (0, get_cloud_logging_client_1.getCloudLoggingClient)();
169
- const listLogEntriesRequest = {
170
- resourceNames: [`projects/${process.env.REMOTION_GCP_PROJECT_ID}`],
171
- filter: `logName=projects/${process.env.REMOTION_GCP_PROJECT_ID}/logs/run.googleapis.com%2Fvarlog%2Fsystem AND (severity=WARNING OR severity=ERROR) AND timestamp >= "${res.requestStartTime}"`,
172
- };
173
- const logCheckCountdown = cli_1.CliInternals.createOverwriteableCliOutput({
174
- quiet: cli_1.CliInternals.quietFlagProvided(),
175
- cancelSignal: null,
176
- updatesDontOverwrite: false,
177
- indent: false,
178
- });
179
- await (() => {
180
- return new Promise((resolve) => {
181
- let timeLeft = 30;
182
- const intervalId = setInterval(() => {
183
- logCheckCountdown.update(`GCP Cloud Logging takes time to ingest and index logs.\nFetching recent error/warning logs in ${timeLeft} seconds`, false);
184
- timeLeft--;
185
- if (timeLeft < 0) {
186
- logCheckCountdown.update('Fetching logs...\n\n', false);
187
- clearInterval(intervalId);
188
- resolve();
189
- }
190
- }, 1000);
191
- });
192
- })();
193
- const iterableLogListEntries = await cloudLoggingClient.listLogEntriesAsync(listLogEntriesRequest);
194
- for await (const logResponse of iterableLogListEntries) {
195
- const responseDate = new Date(Number(logResponse.timestamp.seconds) * 1000 +
196
- Number(logResponse.timestamp.nanos) / 1000000);
197
- const convertedDate = responseDate.toLocaleString();
198
- log_1.Log.info(convertedDate);
199
- log_1.Log.info(logResponse.textPayload);
200
- log_1.Log.info();
201
- }
155
+ if (res.type === 'crash') {
156
+ (0, cloudrun_crash_logs_1.displayCrashLogs)(res);
202
157
  }
203
- else if (res.status === 'success') {
158
+ else if (res.type === 'success') {
204
159
  renderProgress.doneIn = Date.now() - renderStart;
205
160
  updateProgress();
206
161
  log_1.Log.info(`
@@ -0,0 +1,2 @@
1
+ export declare const RENDER_MEDIA_SUBCOMMAND = "media";
2
+ export declare const renderMediaSubcommand: (args: string[], remotionRoot: string) => Promise<void>;
@@ -0,0 +1,156 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderMediaSubcommand = exports.RENDER_MEDIA_SUBCOMMAND = void 0;
4
+ const cli_1 = require("@remotion/cli");
5
+ const render_media_on_cloudrun_1 = require("../../../api/render-media-on-cloudrun");
6
+ // import {validateMaxRetries} from '../../../shared/validate-retries';
7
+ const config_1 = require("@remotion/cli/config");
8
+ const renderer_1 = require("@remotion/renderer");
9
+ const download_file_1 = require("../../../api/download-file");
10
+ const validate_serveurl_1 = require("../../../shared/validate-serveurl");
11
+ const args_1 = require("../../args");
12
+ const log_1 = require("../../log");
13
+ const renderArgsCheck_1 = require("./helpers/renderArgsCheck");
14
+ exports.RENDER_MEDIA_SUBCOMMAND = 'media';
15
+ const renderMediaSubcommand = async (args, remotionRoot) => {
16
+ var _a;
17
+ const { serveUrl, cloudRunUrl, outName, forceBucketName, downloadName, privacy, region, } = await (0, renderArgsCheck_1.renderArgsCheck)(exports.RENDER_MEDIA_SUBCOMMAND, args);
18
+ const { codec, reason: codecReason } = cli_1.CliInternals.getFinalOutputCodec({
19
+ cliFlag: cli_1.CliInternals.parsedCli.codec,
20
+ downloadName,
21
+ outName: outName !== null && outName !== void 0 ? outName : null,
22
+ configFile: (_a = config_1.ConfigInternals.getOutputCodecOrUndefined()) !== null && _a !== void 0 ? _a : null,
23
+ uiCodec: null,
24
+ });
25
+ const imageFormat = args_1.parsedCloudrunCli['image-format'];
26
+ const audioCodec = args_1.parsedCloudrunCli['audio-codec'];
27
+ const { chromiumOptions, crf, envVariables, frameRange, inputProps, logLevel, puppeteerTimeout, pixelFormat, proResProfile, jpegQuality, scale, everyNthFrame, numberOfGifLoops, muted, audioBitrate, videoBitrate, height, width, browserExecutable, port, } = await cli_1.CliInternals.getCliOptions({
28
+ type: 'series',
29
+ isLambda: true,
30
+ remotionRoot,
31
+ });
32
+ let composition = args[1];
33
+ if (!composition) {
34
+ log_1.Log.info('No compositions passed. Fetching compositions...');
35
+ (0, validate_serveurl_1.validateServeUrl)(serveUrl);
36
+ const server = renderer_1.RenderInternals.prepareServer({
37
+ concurrency: 1,
38
+ indent: false,
39
+ port,
40
+ remotionRoot,
41
+ verbose: renderer_1.RenderInternals.isEqualOrBelowLogLevel(logLevel, 'verbose'),
42
+ webpackConfigOrServeUrl: serveUrl,
43
+ });
44
+ const { compositionId } = await cli_1.CliInternals.getCompositionWithDimensionOverride({
45
+ args,
46
+ compositionIdFromUi: null,
47
+ browserExecutable,
48
+ chromiumOptions,
49
+ envVariables,
50
+ height,
51
+ indent: false,
52
+ inputProps,
53
+ port,
54
+ puppeteerInstance: undefined,
55
+ serveUrlOrWebpackUrl: serveUrl,
56
+ timeoutInMilliseconds: puppeteerTimeout,
57
+ verbose: renderer_1.RenderInternals.isEqualOrBelowLogLevel(logLevel, 'verbose'),
58
+ width,
59
+ server: await server,
60
+ });
61
+ composition = compositionId;
62
+ }
63
+ // Todo: Check cloudRunUrl is valid, as the error message is obtuse
64
+ cli_1.CliInternals.Log.info(cli_1.CliInternals.chalk.gray(`
65
+ Cloud Run Service URL = ${cloudRunUrl}
66
+ Region = ${region}
67
+ Type = media
68
+ Composition = ${composition}
69
+ Codec = ${codec}
70
+ Output Bucket = ${forceBucketName}
71
+ Output File = ${outName !== null && outName !== void 0 ? outName : 'out.mp4'}
72
+ Output File Privacy = ${privacy}
73
+ ${downloadName ? ` Downloaded File = ${downloadName}` : ''}
74
+ `.trim()));
75
+ log_1.Log.info();
76
+ const renderStart = Date.now();
77
+ const progressBar = cli_1.CliInternals.createOverwriteableCliOutput({
78
+ quiet: cli_1.CliInternals.quietFlagProvided(),
79
+ cancelSignal: null,
80
+ updatesDontOverwrite: false,
81
+ indent: false,
82
+ });
83
+ const renderProgress = {
84
+ doneIn: null,
85
+ progress: 0,
86
+ };
87
+ const updateProgress = () => {
88
+ progressBar.update([
89
+ `Rendering on Cloud Run: `,
90
+ cli_1.CliInternals.makeProgressBar(renderProgress.progress),
91
+ `${renderProgress.doneIn === null ? 'Rendering' : 'Rendered'}`,
92
+ renderProgress.doneIn === null
93
+ ? `${Math.round(renderProgress.progress * 100)}%`
94
+ : cli_1.CliInternals.chalk.gray(`${renderProgress.doneIn}ms`),
95
+ ].join(' '), false);
96
+ };
97
+ const updateRenderProgress = (progress) => {
98
+ renderProgress.progress = progress;
99
+ updateProgress();
100
+ };
101
+ const res = await (0, render_media_on_cloudrun_1.renderMediaOnCloudrun)({
102
+ cloudRunUrl,
103
+ serveUrl,
104
+ region,
105
+ inputProps,
106
+ codec: codec,
107
+ imageFormat,
108
+ crf: crf !== null && crf !== void 0 ? crf : undefined,
109
+ envVariables,
110
+ pixelFormat,
111
+ proResProfile,
112
+ jpegQuality,
113
+ composition,
114
+ privacy,
115
+ frameRange: frameRange !== null && frameRange !== void 0 ? frameRange : undefined,
116
+ outName,
117
+ chromiumOptions,
118
+ scale,
119
+ numberOfGifLoops,
120
+ everyNthFrame,
121
+ muted,
122
+ audioBitrate,
123
+ videoBitrate,
124
+ forceHeight: height,
125
+ forceWidth: width,
126
+ audioCodec,
127
+ forceBucketName,
128
+ updateRenderProgress,
129
+ logLevel: config_1.ConfigInternals.Logging.getLogLevel(),
130
+ });
131
+ renderProgress.doneIn = Date.now() - renderStart;
132
+ updateProgress();
133
+ log_1.Log.info(`
134
+
135
+ `);
136
+ log_1.Log.info(cli_1.CliInternals.chalk.blueBright(`
137
+ ${res.publicUrl ? `Public URL = ${decodeURIComponent(res.publicUrl)}` : ``}
138
+ Cloud Storage Uri = ${res.cloudStorageUri}
139
+ Size (KB) = ${Math.round(Number(res.size) / 1000)}
140
+ Bucket Name = ${res.bucketName}
141
+ Privacy = ${res.privacy}
142
+ Render ID = ${res.renderId}
143
+ Codec = ${codec} (${codecReason})
144
+ `.trim()));
145
+ if (downloadName) {
146
+ log_1.Log.info('');
147
+ log_1.Log.info('downloading file...');
148
+ const destination = await (0, download_file_1.downloadFile)({
149
+ bucketName: res.bucketName,
150
+ gsutilURI: res.cloudStorageUri,
151
+ downloadName,
152
+ });
153
+ log_1.Log.info(cli_1.CliInternals.chalk.blueBright(`Downloaded file to ${destination}!`));
154
+ }
155
+ };
156
+ exports.renderMediaSubcommand = renderMediaSubcommand;
@@ -0,0 +1,2 @@
1
+ export declare const RENDER_STILL_SUBCOMMAND = "still";
2
+ export declare const renderStillSubcommand: (args: string[], remotionRoot: string) => Promise<void>;
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderStillSubcommand = exports.RENDER_STILL_SUBCOMMAND = void 0;
4
+ const cli_1 = require("@remotion/cli");
5
+ const config_1 = require("@remotion/cli/config");
6
+ const renderer_1 = require("@remotion/renderer");
7
+ const download_file_1 = require("../../../api/download-file");
8
+ const render_still_on_cloudrun_1 = require("../../../api/render-still-on-cloudrun");
9
+ const validate_serveurl_1 = require("../../../shared/validate-serveurl");
10
+ const log_1 = require("../../log");
11
+ const renderArgsCheck_1 = require("./helpers/renderArgsCheck");
12
+ exports.RENDER_STILL_SUBCOMMAND = 'still';
13
+ const renderStillSubcommand = async (args, remotionRoot) => {
14
+ var _a, _b;
15
+ const { serveUrl, cloudRunUrl, outName, forceBucketName, privacy, downloadName, region, } = await (0, renderArgsCheck_1.renderArgsCheck)(exports.RENDER_STILL_SUBCOMMAND, args);
16
+ const { chromiumOptions, envVariables, inputProps, logLevel, puppeteerTimeout, jpegQuality, stillFrame, scale, height, width, browserExecutable, port, } = await cli_1.CliInternals.getCliOptions({
17
+ type: 'still',
18
+ isLambda: true,
19
+ remotionRoot,
20
+ });
21
+ let composition = args[1];
22
+ if (!composition) {
23
+ log_1.Log.info('No compositions passed. Fetching compositions...');
24
+ (0, validate_serveurl_1.validateServeUrl)(serveUrl);
25
+ const server = renderer_1.RenderInternals.prepareServer({
26
+ concurrency: 1,
27
+ indent: false,
28
+ port,
29
+ remotionRoot,
30
+ verbose: renderer_1.RenderInternals.isEqualOrBelowLogLevel(logLevel, 'verbose'),
31
+ webpackConfigOrServeUrl: serveUrl,
32
+ });
33
+ const { compositionId } = await cli_1.CliInternals.getCompositionWithDimensionOverride({
34
+ args,
35
+ compositionIdFromUi: null,
36
+ indent: false,
37
+ serveUrlOrWebpackUrl: serveUrl,
38
+ verbose: renderer_1.RenderInternals.isEqualOrBelowLogLevel(logLevel, 'verbose'),
39
+ browserExecutable,
40
+ chromiumOptions,
41
+ envVariables,
42
+ inputProps,
43
+ port,
44
+ puppeteerInstance: undefined,
45
+ timeoutInMilliseconds: puppeteerTimeout,
46
+ height,
47
+ width,
48
+ server: await server,
49
+ });
50
+ composition = compositionId;
51
+ }
52
+ const { format: imageFormat, source: imageFormatReason } = cli_1.CliInternals.determineFinalStillImageFormat({
53
+ downloadName,
54
+ outName: outName !== null && outName !== void 0 ? outName : null,
55
+ cliFlag: (_a = cli_1.CliInternals.parsedCli['image-format']) !== null && _a !== void 0 ? _a : null,
56
+ isLambda: true,
57
+ fromUi: null,
58
+ configImageFormat: (_b = config_1.ConfigInternals.getUserPreferredStillImageFormat()) !== null && _b !== void 0 ? _b : null,
59
+ });
60
+ log_1.Log.verbose(`Image format: (${imageFormat}), ${imageFormatReason}`);
61
+ // Todo: Check cloudRunUrl is valid, as the error message is obtuse
62
+ cli_1.CliInternals.Log.info(cli_1.CliInternals.chalk.gray(`
63
+ Cloud Run Service URL = ${cloudRunUrl}
64
+ Region = ${region}
65
+ Type = still
66
+ Composition = ${composition}
67
+ Output Bucket = ${forceBucketName}
68
+ Output File = ${outName !== null && outName !== void 0 ? outName : 'out.png'}
69
+ Output File Privacy = ${privacy}
70
+ ${downloadName ? ` Downloaded File = ${downloadName}` : ''}
71
+ `.trim()));
72
+ log_1.Log.info();
73
+ const renderStart = Date.now();
74
+ const progressBar = cli_1.CliInternals.createOverwriteableCliOutput({
75
+ quiet: cli_1.CliInternals.quietFlagProvided(),
76
+ cancelSignal: null,
77
+ updatesDontOverwrite: false,
78
+ indent: false,
79
+ });
80
+ let doneIn = null;
81
+ const updateProgress = (newline) => {
82
+ progressBar.update([
83
+ `Rendering on Cloud Run:`,
84
+ `${doneIn === null ? '...' : `Rendered in ${doneIn}ms`}`,
85
+ ].join(' '), newline);
86
+ };
87
+ const res = await (0, render_still_on_cloudrun_1.renderStillOnCloudrun)({
88
+ cloudRunUrl,
89
+ serveUrl,
90
+ region,
91
+ inputProps,
92
+ imageFormat,
93
+ composition,
94
+ privacy,
95
+ envVariables,
96
+ frame: stillFrame,
97
+ jpegQuality,
98
+ chromiumOptions,
99
+ scale,
100
+ forceHeight: height,
101
+ forceWidth: width,
102
+ forceBucketName,
103
+ outName,
104
+ logLevel: config_1.ConfigInternals.Logging.getLogLevel(),
105
+ });
106
+ doneIn = Date.now() - renderStart;
107
+ updateProgress(true);
108
+ log_1.Log.info(cli_1.CliInternals.chalk.gray(`Cloud Storage Uri = ${res.cloudStorageUri}`));
109
+ log_1.Log.info(cli_1.CliInternals.chalk.gray(`Render ID = ${res.renderId}`));
110
+ log_1.Log.info(cli_1.CliInternals.chalk.gray(`${Math.round(Number(res.size) / 1000)} KB, Privacy: ${res.privacy}, Bucket: ${res.bucketName}`));
111
+ log_1.Log.info(cli_1.CliInternals.chalk.blue(`○ ${res.publicUrl}`));
112
+ if (downloadName) {
113
+ log_1.Log.info('');
114
+ log_1.Log.info('downloading file...');
115
+ const destination = await (0, download_file_1.downloadFile)({
116
+ bucketName: res.bucketName,
117
+ gsutilURI: res.cloudStorageUri,
118
+ downloadName,
119
+ });
120
+ log_1.Log.info(cli_1.CliInternals.chalk.blueBright(`Downloaded file to ${destination}!`));
121
+ }
122
+ };
123
+ exports.renderStillSubcommand = renderStillSubcommand;