@remotion/renderer 4.0.126 → 4.0.128

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 (59) hide show
  1. package/dist/assets/convert-assets-to-file-urls.d.ts +2 -1
  2. package/dist/assets/convert-assets-to-file-urls.js +6 -4
  3. package/dist/assets/download-map.d.ts +6 -2
  4. package/dist/assets/ffmpeg-volume-expression.js +7 -3
  5. package/dist/calculate-ffmpeg-filters.d.ts +4 -2
  6. package/dist/calculate-ffmpeg-filters.js +10 -17
  7. package/dist/check-apple-silicon.d.ts +1 -3
  8. package/dist/check-apple-silicon.js +2 -32
  9. package/dist/client.d.ts +57 -21
  10. package/dist/combine-audio.js +6 -6
  11. package/dist/combine-videos.js +1 -0
  12. package/dist/compress-audio.d.ts +2 -2
  13. package/dist/compress-audio.js +4 -7
  14. package/dist/create-audio.d.ts +11 -4
  15. package/dist/create-audio.js +7 -5
  16. package/dist/create-combined-video.d.ts +3 -2
  17. package/dist/create-combined-video.js +7 -1
  18. package/dist/create-silent-audio.d.ts +2 -2
  19. package/dist/create-silent-audio.js +2 -2
  20. package/dist/does-have-m2-bug.d.ts +3 -0
  21. package/dist/does-have-m2-bug.js +12 -0
  22. package/dist/get-extension-from-audio-codec.d.ts +2 -2
  23. package/dist/get-extra-frames-to-capture.d.ts +2 -1
  24. package/dist/get-extra-frames-to-capture.js +30 -23
  25. package/dist/index.d.ts +5 -5
  26. package/dist/logger.js +3 -1
  27. package/dist/merge-audio-track.d.ts +1 -1
  28. package/dist/merge-audio-track.js +7 -11
  29. package/dist/options/gl.d.ts +3 -3
  30. package/dist/options/index.d.ts +39 -3
  31. package/dist/options/index.js +4 -0
  32. package/dist/options/options-map.d.ts +18 -18
  33. package/dist/options/options-map.js +1 -1
  34. package/dist/options/prores-profile.d.ts +0 -0
  35. package/dist/options/prores-profile.js +1 -0
  36. package/dist/options/{separate-audio-to.d.ts → public-dir.d.ts} +5 -5
  37. package/dist/options/public-dir.js +37 -0
  38. package/dist/options/public-path.d.ts +18 -0
  39. package/dist/options/public-path.js +37 -0
  40. package/dist/preprocess-audio-track.d.ts +3 -1
  41. package/dist/preprocess-audio-track.js +7 -7
  42. package/dist/render-frames.d.ts +6 -0
  43. package/dist/render-frames.js +92 -42
  44. package/dist/render-media.d.ts +1 -0
  45. package/dist/render-media.js +5 -2
  46. package/dist/stitch-frames-to-video.d.ts +1 -1
  47. package/dist/stitch-frames-to-video.js +9 -9
  48. package/dist/stringify-ffmpeg-filter.d.ts +3 -2
  49. package/dist/stringify-ffmpeg-filter.js +56 -14
  50. package/dist/x264-preset.d.ts +15 -0
  51. package/dist/x264-preset.js +26 -1
  52. package/package.json +9 -9
  53. package/dist/can-concatenate-seamlessly.d.ts +0 -3
  54. package/dist/can-concatenate-seamlessly.js +0 -7
  55. package/dist/options/separate-audio-to.js +0 -31
  56. package/dist/should-seamless.d.ts +0 -3
  57. package/dist/should-seamless.js +0 -7
  58. package/dist/supported-audio-codecs.d.ts +0 -13
  59. package/dist/supported-audio-codecs.js +0 -16
@@ -5,16 +5,25 @@ Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.getExtraFramesToCapture = void 0;
6
6
  const combine_audio_1 = require("./combine-audio");
7
7
  const sample_rate_1 = require("./sample-rate");
8
+ // Inspired by https://github.com/wistia/seamless-aac-split-and-stitch-demo
9
+ // We can seamlessly concatenate AAC files if we capture a bit of extra audio on both sides in each chunk and then align the audio correctly.
10
+ // This function calculates which extra frames should be evaluated for their audio content.
8
11
  const getExtraFramesToCapture = ({ compositionStart, realFrameRange, fps, forSeamlessAacConcatenation, }) => {
12
+ // If the feature is disabled, don't capture extra frames.
9
13
  if (!forSeamlessAacConcatenation) {
10
14
  return {
11
- extraFramesToCaptureAssets: [],
15
+ extraFramesToCaptureAssetsBackend: [],
16
+ extraFramesToCaptureAssetsFrontend: [],
12
17
  chunkLengthInSeconds: (realFrameRange[1] - realFrameRange[0] + 1) / fps,
13
18
  trimLeftOffset: 0,
14
19
  trimRightOffset: 0,
15
20
  };
16
21
  }
17
- const chunkStart = realFrameRange[0] / fps;
22
+ // If this video is just a chunk as part of a larger video,
23
+ // We also need to know the start time of this chunk to align it correctly.
24
+ const chunkStart = realFrameRange[0];
25
+ // If we are only rendering a portion of the composition, we also need to account for that.
26
+ // It cannot be that the chunk start time is earlier than the composition time.
18
27
  if (chunkStart < compositionStart) {
19
28
  throw new Error('chunkStart may not be below compositionStart');
20
29
  }
@@ -22,31 +31,29 @@ const getExtraFramesToCapture = ({ compositionStart, realFrameRange, fps, forSea
22
31
  if (realLeftEnd < 0) {
23
32
  throw new Error('chunkStat - compositionStart may not be below 0');
24
33
  }
25
- const realRightEnd = realLeftEnd + (realFrameRange[1] - realFrameRange[0] + 1) / fps;
26
- const aacAdjustedLeftEnd = Math.max(0, (0, combine_audio_1.getClosestAlignedTime)(realLeftEnd) - 2 * (1024 / sample_rate_1.DEFAULT_SAMPLE_RATE));
27
- const aacAdjustedRightEnd = (0, combine_audio_1.getClosestAlignedTime)(realRightEnd) + 2 * (1024 / sample_rate_1.DEFAULT_SAMPLE_RATE);
28
- const startTimeWithoutOffset = Math.floor(aacAdjustedLeftEnd * fps);
29
- // TODO: Prevent floating point issues by dividing and then multiplying by FPS
30
- const startFrame = startTimeWithoutOffset + compositionStart * fps;
31
- const trimLeftOffset = (aacAdjustedLeftEnd * fps - startTimeWithoutOffset) / fps;
32
- const endFrame = Math.ceil(aacAdjustedRightEnd * fps) + compositionStart * fps;
33
- const trimRightOffset = (aacAdjustedRightEnd * fps - Math.ceil(aacAdjustedRightEnd * fps)) / fps;
34
- const extraFramesToCaptureAudioOnly = new Array(realFrameRange[0] - startFrame)
34
+ const realRightEnd = realLeftEnd + (realFrameRange[1] - realFrameRange[0] + 1);
35
+ // Find the closest AAC packet border and add two AAC packet padding.
36
+ const aacAdjustedLeftEnd = Math.max(0, (0, combine_audio_1.getClosestAlignedTime)(realLeftEnd / fps) - 2 * (1024 / sample_rate_1.DEFAULT_SAMPLE_RATE));
37
+ const aacAdjustedRightEnd = (0, combine_audio_1.getClosestAlignedTime)(realRightEnd / fps) +
38
+ 2 * (1024 / sample_rate_1.DEFAULT_SAMPLE_RATE);
39
+ // Now find the additional frames that we need to capture to have enough audio
40
+ const alignedStartFrameWithoutOffset = Math.floor(aacAdjustedLeftEnd * fps);
41
+ const alignedStartFrame = alignedStartFrameWithoutOffset + compositionStart;
42
+ const alignedEndFrame = Math.ceil(aacAdjustedRightEnd * fps) + compositionStart;
43
+ const extraFramesToCaptureAudioOnlyFrontend = new Array(realFrameRange[0] - alignedStartFrame)
35
44
  .fill(true)
36
- .map((_, f) => {
37
- return f + startFrame;
38
- });
39
- const extraFramesToCaptureAudioOnlyBackend = new Array(endFrame - realFrameRange[1] - 1)
45
+ .map((_, f) => f + alignedStartFrame);
46
+ const extraFramesToCaptureAudioOnlyBackend = new Array(alignedEndFrame - realFrameRange[1] - 1)
40
47
  .fill(true)
41
- .map((_, f) => {
42
- return f + realFrameRange[1] + 1;
43
- });
48
+ .map((_, f) => f + realFrameRange[1] + 1);
49
+ // But now, we might have too much audio, since the extra frames only have a `1 / fps` step.
50
+ // When creating the lossless audio for a chunk, we need to shave that extra audio off.
51
+ const trimLeftOffset = (aacAdjustedLeftEnd * fps - alignedStartFrameWithoutOffset) / fps;
52
+ const trimRightOffset = (aacAdjustedRightEnd * fps - Math.ceil(aacAdjustedRightEnd * fps)) / fps;
44
53
  const chunkLengthInSeconds = aacAdjustedRightEnd - aacAdjustedLeftEnd;
45
54
  return {
46
- extraFramesToCaptureAssets: [
47
- ...extraFramesToCaptureAudioOnly,
48
- ...extraFramesToCaptureAudioOnlyBackend,
49
- ],
55
+ extraFramesToCaptureAssetsFrontend: extraFramesToCaptureAudioOnlyFrontend,
56
+ extraFramesToCaptureAssetsBackend: extraFramesToCaptureAudioOnlyBackend,
50
57
  chunkLengthInSeconds,
51
58
  trimLeftOffset,
52
59
  trimRightOffset,
package/dist/index.d.ts CHANGED
@@ -142,8 +142,8 @@ export declare const RenderInternals: {
142
142
  validPixelFormats: readonly ["yuv420p", "yuva420p", "yuv422p", "yuv444p", "yuv420p10le", "yuv422p10le", "yuv444p10le", "yuva444p10le"];
143
143
  DEFAULT_BROWSER: "chrome";
144
144
  validateFrameRange: (frameRange: import("./frame-range").FrameRange | null) => void;
145
- DEFAULT_OPENGL_RENDERER: "angle" | "swangle" | "egl" | "swiftshader" | "vulkan" | "angle-egl" | null;
146
- validateOpenGlRenderer: (option: unknown) => "angle" | "swangle" | "egl" | "swiftshader" | "vulkan" | "angle-egl" | null;
145
+ DEFAULT_OPENGL_RENDERER: "swangle" | "angle" | "egl" | "swiftshader" | "vulkan" | "angle-egl" | null;
146
+ validateOpenGlRenderer: (option: unknown) => "swangle" | "angle" | "egl" | "swiftshader" | "vulkan" | "angle-egl" | null;
147
147
  validCodecs: readonly ["h264", "h265", "vp8", "vp9", "mp3", "aac", "wav", "prores", "h264-mkv", "h264-ts", "gif"];
148
148
  DEFAULT_PIXEL_FORMAT: "yuv420p" | "yuva420p" | "yuv422p" | "yuv444p" | "yuv420p10le" | "yuv422p10le" | "yuv444p10le" | "yuva444p10le";
149
149
  validateJpegQuality: (q: unknown) => void;
@@ -353,8 +353,8 @@ export declare const RenderInternals: {
353
353
  }) => execa.ExecaChildProcess<string>;
354
354
  validStillImageFormats: readonly ["png", "jpeg", "pdf", "webp"];
355
355
  validVideoImageFormats: readonly ["png", "jpeg", "none"];
356
- DEFAULT_STILL_IMAGE_FORMAT: "jpeg" | "png" | "webp" | "pdf";
357
- DEFAULT_VIDEO_IMAGE_FORMAT: "jpeg" | "png" | "none";
356
+ DEFAULT_STILL_IMAGE_FORMAT: "png" | "jpeg" | "pdf" | "webp";
357
+ DEFAULT_VIDEO_IMAGE_FORMAT: "png" | "jpeg" | "none";
358
358
  DEFAULT_JPEG_QUALITY: number;
359
359
  chalk: {
360
360
  enabled: () => boolean;
@@ -453,7 +453,7 @@ export declare const RenderInternals: {
453
453
  frame: number;
454
454
  serializedInputPropsWithCustomSchema: string;
455
455
  serializedResolvedPropsWithCustomSchema: string;
456
- imageFormat: "jpeg" | "png" | "webp" | "pdf";
456
+ imageFormat: "png" | "jpeg" | "pdf" | "webp";
457
457
  jpegQuality: number;
458
458
  puppeteerInstance: HeadlessBrowser | null;
459
459
  envVariables: Record<string, string>;
package/dist/logger.js CHANGED
@@ -29,7 +29,9 @@ exports.Log = {
29
29
  },
30
30
  info: (options, ...args) => {
31
31
  (0, repro_1.writeInRepro)('info', ...args);
32
- return console.log(...[options.indent ? exports.INDENT_TOKEN : null].filter(truthy_1.truthy).concat(args));
32
+ if ((0, log_level_1.isEqualOrBelowLogLevel)(options.logLevel, 'info')) {
33
+ return console.log(...[options.indent ? exports.INDENT_TOKEN : null].filter(truthy_1.truthy).concat(args));
34
+ }
33
35
  },
34
36
  warn: (options, ...args) => {
35
37
  (0, repro_1.writeInRepro)('warn', ...args);
@@ -13,7 +13,7 @@ type Options = {
13
13
  cancelSignal: CancelSignal | undefined;
14
14
  onProgress: (progress: number) => void;
15
15
  fps: number;
16
- expectedFrames: number;
16
+ chunkLengthInSeconds: number;
17
17
  };
18
18
  export declare const mergeAudioTrack: (options: Options) => Promise<void>;
19
19
  export {};
@@ -11,18 +11,16 @@ const create_ffmpeg_complex_filter_1 = require("./create-ffmpeg-complex-filter")
11
11
  const create_ffmpeg_merge_filter_1 = require("./create-ffmpeg-merge-filter");
12
12
  const create_silent_audio_1 = require("./create-silent-audio");
13
13
  const delete_directory_1 = require("./delete-directory");
14
- const logger_1 = require("./logger");
15
14
  const p_limit_1 = require("./p-limit");
16
15
  const parse_ffmpeg_progress_1 = require("./parse-ffmpeg-progress");
17
16
  const tmp_dir_1 = require("./tmp-dir");
18
17
  const truthy_1 = require("./truthy");
19
- const mergeAudioTrackUnlimited = async ({ outName, files, downloadMap, remotionRoot, indent, logLevel, binariesDirectory, cancelSignal, onProgress, fps, expectedFrames, }) => {
18
+ const mergeAudioTrackUnlimited = async ({ outName, files, downloadMap, remotionRoot, indent, logLevel, binariesDirectory, cancelSignal, onProgress, fps, chunkLengthInSeconds, }) => {
20
19
  var _a;
21
- const numberOfSeconds = Number((expectedFrames / fps).toFixed(3));
22
20
  if (files.length === 0) {
23
21
  await (0, create_silent_audio_1.createSilentAudio)({
24
22
  outName,
25
- numberOfSeconds,
23
+ chunkLengthInSeconds,
26
24
  indent,
27
25
  logLevel,
28
26
  binariesDirectory,
@@ -48,7 +46,7 @@ const mergeAudioTrackUnlimited = async ({ outName, files, downloadMap, remotionR
48
46
  const chunkOutname = node_path_1.default.join(tempPath, `chunk-${i}.wav`);
49
47
  await (0, exports.mergeAudioTrack)({
50
48
  files: chunkFiles,
51
- expectedFrames,
49
+ chunkLengthInSeconds,
52
50
  outName: chunkOutname,
53
51
  downloadMap,
54
52
  remotionRoot,
@@ -84,7 +82,7 @@ const mergeAudioTrackUnlimited = async ({ outName, files, downloadMap, remotionR
84
82
  callProgress();
85
83
  },
86
84
  fps,
87
- expectedFrames,
85
+ chunkLengthInSeconds,
88
86
  });
89
87
  return;
90
88
  }
@@ -97,6 +95,7 @@ const mergeAudioTrackUnlimited = async ({ outName, files, downloadMap, remotionR
97
95
  downloadMap,
98
96
  });
99
97
  const args = [
98
+ ['-hide_banner'],
100
99
  ...files.map((f) => ['-i', f.outName]),
101
100
  mergeFilter,
102
101
  ['-c:a', 'pcm_s16le'],
@@ -116,11 +115,8 @@ const mergeAudioTrackUnlimited = async ({ outName, files, downloadMap, remotionR
116
115
  (_a = task.stderr) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
117
116
  const utf8 = data.toString('utf8');
118
117
  const parsed = (0, parse_ffmpeg_progress_1.parseFfmpegProgress)(utf8, fps);
119
- if (parsed === undefined) {
120
- logger_1.Log.verbose({ indent, logLevel }, utf8);
121
- }
122
- else {
123
- onProgress(parsed / expectedFrames);
118
+ if (parsed !== undefined) {
119
+ onProgress(parsed / (chunkLengthInSeconds * fps));
124
120
  }
125
121
  });
126
122
  await task;
@@ -1,19 +1,19 @@
1
1
  export declare const validOpenGlRenderers: readonly ["swangle", "angle", "egl", "swiftshader", "vulkan", "angle-egl"];
2
2
  export type OpenGlRenderer = (typeof validOpenGlRenderers)[number];
3
3
  export declare const DEFAULT_OPENGL_RENDERER: OpenGlRenderer | null;
4
- export declare const getChromiumOpenGlRenderer: () => "angle" | "swangle" | "egl" | "swiftshader" | "vulkan" | "angle-egl" | null;
4
+ export declare const getChromiumOpenGlRenderer: () => "swangle" | "angle" | "egl" | "swiftshader" | "vulkan" | "angle-egl" | null;
5
5
  export declare const setChromiumOpenGlRenderer: (renderer: OpenGlRenderer) => void;
6
6
  export declare const glOption: {
7
7
  cliFlag: "gl";
8
8
  docLink: string;
9
9
  name: string;
10
- type: "angle" | "swangle" | "egl" | "swiftshader" | "vulkan" | "angle-egl" | null;
10
+ type: "swangle" | "angle" | "egl" | "swiftshader" | "vulkan" | "angle-egl" | null;
11
11
  ssrName: string;
12
12
  description: () => import("react/jsx-runtime").JSX.Element;
13
13
  getValue: ({ commandLine }: {
14
14
  commandLine: Record<string, unknown>;
15
15
  }) => {
16
- value: "angle" | "swangle" | "egl" | "swiftshader" | "vulkan" | "angle-egl";
16
+ value: "swangle" | "angle" | "egl" | "swiftshader" | "vulkan" | "angle-egl";
17
17
  source: string;
18
18
  } | {
19
19
  value: null;
@@ -245,19 +245,19 @@ export declare const allOptions: {
245
245
  cliFlag: "gl";
246
246
  docLink: string;
247
247
  name: string;
248
- type: "angle" | "swangle" | "egl" | "swiftshader" | "vulkan" | "angle-egl" | null;
248
+ type: "swangle" | "angle" | "egl" | "swiftshader" | "vulkan" | "angle-egl" | null;
249
249
  ssrName: string;
250
250
  description: () => import("react/jsx-runtime").JSX.Element;
251
251
  getValue: ({ commandLine }: {
252
252
  commandLine: Record<string, unknown>;
253
253
  }) => {
254
- value: "angle" | "swangle" | "egl" | "swiftshader" | "vulkan" | "angle-egl";
254
+ value: "swangle" | "angle" | "egl" | "swiftshader" | "vulkan" | "angle-egl";
255
255
  source: string;
256
256
  } | {
257
257
  value: null;
258
258
  source: string;
259
259
  };
260
- setConfig: (value: "angle" | "swangle" | "egl" | "swiftshader" | "vulkan" | "angle-egl" | null) => void;
260
+ setConfig: (value: "swangle" | "angle" | "egl" | "swiftshader" | "vulkan" | "angle-egl" | null) => void;
261
261
  };
262
262
  enableLambdaInsights: {
263
263
  name: string;
@@ -505,6 +505,42 @@ export declare const allOptions: {
505
505
  ssrName: string;
506
506
  type: string | null;
507
507
  };
508
+ publicPathOption: {
509
+ name: string;
510
+ cliFlag: "public-path";
511
+ description: () => import("react/jsx-runtime").JSX.Element;
512
+ ssrName: "publicPath";
513
+ docLink: string;
514
+ getValue: ({ commandLine }: {
515
+ commandLine: Record<string, unknown>;
516
+ }) => {
517
+ source: string;
518
+ value: string;
519
+ } | {
520
+ source: string;
521
+ value: null;
522
+ };
523
+ setConfig: (value: string | null) => void;
524
+ type: string | null;
525
+ };
526
+ publicDirOption: {
527
+ name: string;
528
+ cliFlag: "public-dir";
529
+ description: () => import("react/jsx-runtime").JSX.Element;
530
+ ssrName: "publicDir";
531
+ docLink: string;
532
+ getValue: ({ commandLine }: {
533
+ commandLine: Record<string, unknown>;
534
+ }) => {
535
+ source: string;
536
+ value: string;
537
+ } | {
538
+ source: string;
539
+ value: null;
540
+ };
541
+ setConfig: (value: string | null) => void;
542
+ type: string | null;
543
+ };
508
544
  };
509
545
  export type AvailableOptions = keyof typeof allOptions;
510
546
  export type TypeOfOption<Type> = Type extends AnyRemotionOption<infer X> ? X : never;
@@ -24,6 +24,8 @@ const number_of_gif_loops_1 = require("./number-of-gif-loops");
24
24
  const offthreadvideo_cache_size_1 = require("./offthreadvideo-cache-size");
25
25
  const overwrite_1 = require("./overwrite");
26
26
  const prefer_lossless_1 = require("./prefer-lossless");
27
+ const public_dir_1 = require("./public-dir");
28
+ const public_path_1 = require("./public-path");
27
29
  const repro_1 = require("./repro");
28
30
  const scale_1 = require("./scale");
29
31
  const separate_audio_1 = require("./separate-audio");
@@ -64,4 +66,6 @@ exports.allOptions = {
64
66
  binariesDirectoryOption: binaries_directory_1.binariesDirectoryOption,
65
67
  forSeamlessAacConcatenationOption: for_seamless_aac_concatenation_1.forSeamlessAacConcatenationOption,
66
68
  separateAudioOption: separate_audio_1.separateAudioOption,
69
+ publicPathOption: public_path_1.publicPathOption,
70
+ publicDirOption: public_dir_1.publicDirOption,
67
71
  };
@@ -305,24 +305,6 @@ export declare const optionsMap: {
305
305
  };
306
306
  };
307
307
  readonly stitchFramesToVideo: {
308
- readonly forSeamlessAacConcatenation: {
309
- name: string;
310
- cliFlag: "for-seamless-aac-concatenation";
311
- description: () => import("react/jsx-runtime").JSX.Element;
312
- docLink: string;
313
- getValue: ({ commandLine }: {
314
- commandLine: Record<string, unknown>;
315
- }) => {
316
- source: string;
317
- value: true;
318
- } | {
319
- source: string;
320
- value: false;
321
- };
322
- setConfig: (value: boolean) => void;
323
- ssrName: string;
324
- type: boolean;
325
- };
326
308
  readonly separateAudioTo: {
327
309
  cliFlag: string;
328
310
  description: () => string;
@@ -553,6 +535,24 @@ export declare const optionsMap: {
553
535
  };
554
536
  };
555
537
  readonly renderFrames: {
538
+ readonly forSeamlessAacConcatenation: {
539
+ name: string;
540
+ cliFlag: "for-seamless-aac-concatenation";
541
+ description: () => import("react/jsx-runtime").JSX.Element;
542
+ docLink: string;
543
+ getValue: ({ commandLine }: {
544
+ commandLine: Record<string, unknown>;
545
+ }) => {
546
+ source: string;
547
+ value: true;
548
+ } | {
549
+ source: string;
550
+ value: false;
551
+ };
552
+ setConfig: (value: boolean) => void;
553
+ ssrName: string;
554
+ type: boolean;
555
+ };
556
556
  readonly offthreadVideoCacheSizeInBytes: {
557
557
  name: string;
558
558
  cliFlag: "offthreadvideo-cache-size-in-bytes";
@@ -46,7 +46,6 @@ exports.optionsMap = {
46
46
  audioCodec: audio_codec_1.audioCodecOption,
47
47
  },
48
48
  stitchFramesToVideo: {
49
- forSeamlessAacConcatenation: for_seamless_aac_concatenation_1.forSeamlessAacConcatenationOption,
50
49
  separateAudioTo: separate_audio_1.separateAudioOption,
51
50
  },
52
51
  renderStill: {
@@ -69,6 +68,7 @@ exports.optionsMap = {
69
68
  binariesDirectory: binaries_directory_1.binariesDirectoryOption,
70
69
  },
71
70
  renderFrames: {
71
+ forSeamlessAacConcatenation: for_seamless_aac_concatenation_1.forSeamlessAacConcatenationOption,
72
72
  offthreadVideoCacheSizeInBytes: offthreadvideo_cache_size_1.offthreadVideoCacheSizeInBytesOption,
73
73
  jpegQuality: jpeg_quality_1.jpegQualityOption,
74
74
  logLevel: log_level_1.logLevelOption,
File without changes
@@ -0,0 +1 @@
1
+ "use strict";
@@ -1,6 +1,8 @@
1
- export declare const separateAudioOption: {
2
- cliFlag: string;
1
+ export declare const publicDirOption: {
2
+ name: string;
3
+ cliFlag: "public-dir";
3
4
  description: () => import("react/jsx-runtime").JSX.Element;
5
+ ssrName: "publicDir";
4
6
  docLink: string;
5
7
  getValue: ({ commandLine }: {
6
8
  commandLine: Record<string, unknown>;
@@ -11,8 +13,6 @@ export declare const separateAudioOption: {
11
13
  source: string;
12
14
  value: null;
13
15
  };
14
- name: string;
15
- setConfig: () => never;
16
- ssrName: string;
16
+ setConfig: (value: string | null) => void;
17
17
  type: string | null;
18
18
  };
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.publicDirOption = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const cliFlag = 'public-dir';
6
+ let currentPublicDir = null;
7
+ exports.publicDirOption = {
8
+ name: 'Public Directory',
9
+ cliFlag,
10
+ description: () => {
11
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Define the location of the", ' ', (0, jsx_runtime_1.jsx)("a", { href: "/docs/terminology/public-dir", children: (0, jsx_runtime_1.jsx)("code", { children: "public/ directory" }) }), ". If not defined, Remotion will assume the location is the `public` folder in your Remotion root."] }));
12
+ },
13
+ ssrName: 'publicDir',
14
+ docLink: 'https://www.remotion.dev/docs/terminology/public-dir',
15
+ getValue: ({ commandLine }) => {
16
+ if (commandLine[cliFlag] !== undefined) {
17
+ return {
18
+ source: 'cli',
19
+ value: commandLine[cliFlag],
20
+ };
21
+ }
22
+ if (currentPublicDir !== null) {
23
+ return {
24
+ source: 'config',
25
+ value: currentPublicDir,
26
+ };
27
+ }
28
+ return {
29
+ source: 'default',
30
+ value: null,
31
+ };
32
+ },
33
+ setConfig: (value) => {
34
+ currentPublicDir = value;
35
+ },
36
+ type: '',
37
+ };
@@ -0,0 +1,18 @@
1
+ export declare const publicPathOption: {
2
+ name: string;
3
+ cliFlag: "public-path";
4
+ description: () => import("react/jsx-runtime").JSX.Element;
5
+ ssrName: "publicPath";
6
+ docLink: string;
7
+ getValue: ({ commandLine }: {
8
+ commandLine: Record<string, unknown>;
9
+ }) => {
10
+ source: string;
11
+ value: string;
12
+ } | {
13
+ source: string;
14
+ value: null;
15
+ };
16
+ setConfig: (value: string | null) => void;
17
+ type: string | null;
18
+ };
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.publicPathOption = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const cliFlag = 'public-path';
6
+ let currentPublicPath = null;
7
+ exports.publicPathOption = {
8
+ name: 'Public Path',
9
+ cliFlag,
10
+ description: () => {
11
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["The path of the URL where the bundle is going to be hosted. By default it is ", (0, jsx_runtime_1.jsx)("code", { children: "/" }), ", meaning that the bundle is going to be hosted at the root of the domain (e.g. ", (0, jsx_runtime_1.jsx)("code", { children: "https://localhost:3000/" }), "). If you are deploying to a subdirectory (e.g. ", (0, jsx_runtime_1.jsx)("code", { children: "/sites/my-site/" }), "), you should set this to the subdirectory."] }));
12
+ },
13
+ ssrName: 'publicPath',
14
+ docLink: 'https://www.remotion.dev/docs/renderer',
15
+ getValue: ({ commandLine }) => {
16
+ if (commandLine[cliFlag] !== undefined) {
17
+ return {
18
+ source: 'cli',
19
+ value: commandLine[cliFlag],
20
+ };
21
+ }
22
+ if (currentPublicPath !== null) {
23
+ return {
24
+ source: 'config',
25
+ value: currentPublicPath,
26
+ };
27
+ }
28
+ return {
29
+ source: 'default',
30
+ value: null,
31
+ };
32
+ },
33
+ setConfig: (value) => {
34
+ currentPublicPath = value;
35
+ },
36
+ type: '',
37
+ };
@@ -6,13 +6,15 @@ import type { ProcessedTrack } from './stringify-ffmpeg-filter';
6
6
  type Options = {
7
7
  outName: string;
8
8
  asset: MediaAsset;
9
- expectedFrames: number;
10
9
  fps: number;
11
10
  downloadMap: DownloadMap;
12
11
  indent: boolean;
13
12
  logLevel: LogLevel;
14
13
  binariesDirectory: string | null;
15
14
  cancelSignal: CancelSignal | undefined;
15
+ chunkLengthInSeconds: number;
16
+ trimLeftOffset: number;
17
+ trimRightOffset: number;
16
18
  forSeamlessAacConcatenation: boolean;
17
19
  onProgress: (progress: number) => void;
18
20
  };
@@ -10,7 +10,7 @@ const p_limit_1 = require("./p-limit");
10
10
  const parse_ffmpeg_progress_1 = require("./parse-ffmpeg-progress");
11
11
  const resolve_asset_src_1 = require("./resolve-asset-src");
12
12
  const sample_rate_1 = require("./sample-rate");
13
- const preprocessAudioTrackUnlimited = async ({ outName, asset, expectedFrames, fps, downloadMap, indent, logLevel, binariesDirectory, cancelSignal, forSeamlessAacConcatenation, onProgress, }) => {
13
+ const preprocessAudioTrackUnlimited = async ({ outName, asset, fps, downloadMap, indent, logLevel, binariesDirectory, cancelSignal, onProgress, chunkLengthInSeconds, trimLeftOffset, trimRightOffset, forSeamlessAacConcatenation, }) => {
14
14
  var _a;
15
15
  const { channels, duration } = await (0, get_audio_channels_1.getAudioChannelsAndDuration)({
16
16
  downloadMap,
@@ -22,10 +22,12 @@ const preprocessAudioTrackUnlimited = async ({ outName, asset, expectedFrames, f
22
22
  });
23
23
  const filter = (0, calculate_ffmpeg_filters_1.calculateFfmpegFilter)({
24
24
  asset,
25
- durationInFrames: expectedFrames,
26
25
  fps,
27
26
  channels,
28
27
  assetDuration: duration,
28
+ chunkLengthInSeconds,
29
+ trimLeftOffset,
30
+ trimRightOffset,
29
31
  forSeamlessAacConcatenation,
30
32
  });
31
33
  if (filter === null) {
@@ -33,6 +35,7 @@ const preprocessAudioTrackUnlimited = async ({ outName, asset, expectedFrames, f
33
35
  }
34
36
  const { cleanup, file } = await (0, ffmpeg_filter_file_1.makeFfmpegFilterFile)(filter, downloadMap);
35
37
  const args = [
38
+ ['-hide_banner'],
36
39
  ['-i', (0, resolve_asset_src_1.resolveAssetSrc)(asset.src)],
37
40
  ['-ac', '2'],
38
41
  ['-filter_script:a', file],
@@ -53,11 +56,8 @@ const preprocessAudioTrackUnlimited = async ({ outName, asset, expectedFrames, f
53
56
  (_a = task.stderr) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
54
57
  const utf8 = data.toString('utf8');
55
58
  const parsed = (0, parse_ffmpeg_progress_1.parseFfmpegProgress)(utf8, fps);
56
- if (parsed === undefined) {
57
- logger_1.Log.verbose({ indent, logLevel }, utf8);
58
- }
59
- else {
60
- onProgress(parsed / expectedFrames);
59
+ if (parsed !== undefined) {
60
+ onProgress(parsed / (chunkLengthInSeconds * fps));
61
61
  }
62
62
  });
63
63
  await task;
@@ -1,4 +1,5 @@
1
1
  /// <reference types="node" />
2
+ import type { TAsset } from 'remotion';
2
3
  import type { VideoConfig } from 'remotion/no-react';
3
4
  import type { RenderMediaOnDownload } from './assets/download-and-map-assets-to-file';
4
5
  import type { BrowserExecutable } from './browser-executable';
@@ -39,7 +40,12 @@ export type InternalRenderFramesOptions = {
39
40
  serializedInputPropsWithCustomSchema: string;
40
41
  serializedResolvedPropsWithCustomSchema: string;
41
42
  parallelEncodingEnabled: boolean;
43
+ compositionStart: number;
42
44
  } & ToOptions<typeof optionsMap.renderFrames>;
45
+ export type FrameAndAssets = {
46
+ frame: number;
47
+ assets: TAsset[];
48
+ };
43
49
  export type RenderFramesOptions = {
44
50
  onStart: (data: OnStartData) => void;
45
51
  onFrameUpdate: (framesRendered: number, frameIndex: number, timeToRenderInMilliseconds: number) => void;