@remotion/renderer 4.0.0-alpha13 → 4.0.0-alpha14

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 (149) hide show
  1. package/dist/assets/download-and-map-assets-to-file.d.ts +6 -4
  2. package/dist/assets/download-and-map-assets-to-file.js +30 -6
  3. package/dist/assets/download-file.d.ts +2 -2
  4. package/dist/assets/download-map.d.ts +3 -3
  5. package/dist/assets/ffmpeg-volume-expression.d.ts +2 -2
  6. package/dist/assets/get-audio-channels.d.ts +1 -0
  7. package/dist/assets/get-audio-channels.js +10 -5
  8. package/dist/assets/get-video-stream-duration.d.ts +9 -0
  9. package/dist/assets/get-video-stream-duration.js +71 -0
  10. package/dist/assets/read-file.js +1 -1
  11. package/dist/assets/types.d.ts +4 -4
  12. package/dist/audio-codec.d.ts +2 -2
  13. package/dist/browser/Browser.d.ts +9 -9
  14. package/dist/browser/Browser.js +26 -32
  15. package/dist/browser/BrowserFetcher.d.ts +1 -1
  16. package/dist/browser/BrowserPage.d.ts +11 -2
  17. package/dist/browser/BrowserPage.js +47 -12
  18. package/dist/browser/BrowserRunner.js +19 -2
  19. package/dist/browser/ConsoleMessage.d.ts +1 -1
  20. package/dist/browser/DOMWorld.js +8 -8
  21. package/dist/browser/EvalTypes.d.ts +7 -7
  22. package/dist/browser/FrameManager.js +11 -11
  23. package/dist/browser/JSHandle.js +14 -14
  24. package/dist/browser/LaunchOptions.d.ts +1 -1
  25. package/dist/browser/Launcher.js +0 -1
  26. package/dist/browser/LifecycleWatcher.d.ts +1 -1
  27. package/dist/browser/NetworkEventManager.d.ts +4 -4
  28. package/dist/browser/NodeWebSocketTransport.js +16 -16
  29. package/dist/browser/Product.d.ts +1 -1
  30. package/dist/browser/Target.d.ts +2 -1
  31. package/dist/browser/Target.js +8 -2
  32. package/dist/browser/devtools-types.d.ts +10 -10
  33. package/dist/browser/mitt/index.d.ts +6 -6
  34. package/dist/browser/revisions.d.ts +1 -1
  35. package/dist/browser/should-log-message.d.ts +24 -0
  36. package/dist/browser/should-log-message.js +72 -0
  37. package/dist/browser-executable.d.ts +1 -1
  38. package/dist/browser-log.d.ts +1 -1
  39. package/dist/browser.d.ts +1 -1
  40. package/dist/calculate-sar-dar-pixels.d.ts +9 -0
  41. package/dist/calculate-sar-dar-pixels.js +19 -0
  42. package/dist/chalk/index.d.ts +4 -4
  43. package/dist/codec-supports-media.d.ts +1 -1
  44. package/dist/codec.d.ts +2 -2
  45. package/dist/combine-videos.d.ts +1 -1
  46. package/dist/compositor/compose.d.ts +11 -2
  47. package/dist/compositor/compose.js +15 -4
  48. package/dist/compositor/compositor.d.ts +1 -1
  49. package/dist/compositor/compositor.js +1 -1
  50. package/dist/compositor/payloads.d.ts +5 -5
  51. package/dist/create-ffmpeg-complex-filter.d.ts +4 -1
  52. package/dist/crf.d.ts +1 -1
  53. package/dist/determine-resize-params.d.ts +1 -0
  54. package/dist/determine-resize-params.js +10 -0
  55. package/dist/determine-vcodec-ffmpeg-flags.d.ts +2 -0
  56. package/dist/determine-vcodec-ffmpeg-flags.js +13 -0
  57. package/dist/ensure-ffmpeg.d.ts +18 -0
  58. package/dist/ensure-ffmpeg.js +58 -0
  59. package/dist/ensure-presentation-timestamp.d.ts +15 -0
  60. package/dist/ensure-presentation-timestamp.js +88 -0
  61. package/dist/error-handling/symbolicate-error.js +4 -2
  62. package/dist/extract-frame-from-video.d.ts +16 -0
  63. package/dist/extract-frame-from-video.js +191 -0
  64. package/dist/ffmpeg-executable.d.ts +1 -0
  65. package/dist/ffmpeg-executable.js +2 -0
  66. package/dist/ffmpeg-flags.d.ts +31 -0
  67. package/dist/ffmpeg-flags.js +245 -0
  68. package/dist/ffmpeg-override.d.ts +1 -1
  69. package/dist/file-extensions.d.ts +1 -1
  70. package/dist/frame-range.d.ts +1 -1
  71. package/dist/frame-to-ffmpeg-timestamp.d.ts +1 -0
  72. package/dist/frame-to-ffmpeg-timestamp.js +8 -0
  73. package/dist/get-browser-instance.d.ts +6 -1
  74. package/dist/get-browser-instance.js +9 -4
  75. package/dist/get-can-extract-frames-fast.d.ts +14 -0
  76. package/dist/get-can-extract-frames-fast.js +71 -0
  77. package/dist/get-compositions.d.ts +18 -11
  78. package/dist/get-compositions.js +66 -49
  79. package/dist/get-frame-of-video-slow.d.ts +17 -0
  80. package/dist/get-frame-of-video-slow.js +72 -0
  81. package/dist/get-frame-padded-index.d.ts +1 -1
  82. package/dist/get-video-info.d.ts +8 -0
  83. package/dist/get-video-info.js +59 -0
  84. package/dist/image-format.d.ts +3 -3
  85. package/dist/index.d.ts +110 -21
  86. package/dist/index.js +25 -13
  87. package/dist/is-beyond-last-frame.d.ts +3 -0
  88. package/dist/is-beyond-last-frame.js +12 -0
  89. package/dist/jpeg-quality.d.ts +1 -0
  90. package/dist/jpeg-quality.js +2 -1
  91. package/dist/last-frame-from-video-cache.d.ts +17 -0
  92. package/dist/last-frame-from-video-cache.js +55 -0
  93. package/dist/legacy-webpack-config.d.ts +9 -0
  94. package/dist/legacy-webpack-config.js +13 -0
  95. package/dist/log-level.d.ts +1 -1
  96. package/dist/logger.d.ts +4 -2
  97. package/dist/logger.js +12 -5
  98. package/dist/make-cancel-signal.d.ts +2 -2
  99. package/dist/merge-audio-track.d.ts +1 -1
  100. package/dist/mime-types.js +1 -1
  101. package/dist/offthread-video-server.d.ts +36 -4
  102. package/dist/offthread-video-server.js +48 -4
  103. package/dist/open-browser.d.ts +19 -10
  104. package/dist/open-browser.js +34 -21
  105. package/dist/options/option.d.ts +1 -1
  106. package/dist/parse-browser-error-stack.d.ts +1 -1
  107. package/dist/perf.d.ts +1 -1
  108. package/dist/pixel-format.d.ts +1 -1
  109. package/dist/prepare-server.d.ts +20 -8
  110. package/dist/prepare-server.js +52 -8
  111. package/dist/preprocess-audio-track.d.ts +2 -2
  112. package/dist/prespawn-ffmpeg.d.ts +1 -1
  113. package/dist/prespawn-ffmpeg.js +7 -7
  114. package/dist/prores-profile.d.ts +1 -1
  115. package/dist/provide-screenshot.d.ts +0 -1
  116. package/dist/puppeteer-screenshot.d.ts +0 -1
  117. package/dist/puppeteer-screenshot.js +1 -2
  118. package/dist/quality.d.ts +1 -0
  119. package/dist/quality.js +21 -0
  120. package/dist/render-frames.d.ts +32 -11
  121. package/dist/render-frames.js +112 -77
  122. package/dist/render-media.d.ts +50 -21
  123. package/dist/render-media.js +249 -197
  124. package/dist/render-still.d.ts +33 -18
  125. package/dist/render-still.js +71 -43
  126. package/dist/replace-browser.d.ts +1 -1
  127. package/dist/screenshot-dom-element.d.ts +0 -1
  128. package/dist/screenshot-task.d.ts +0 -1
  129. package/dist/select-composition.d.ts +19 -11
  130. package/dist/select-composition.js +79 -42
  131. package/dist/serve-static.d.ts +2 -3
  132. package/dist/serve-static.js +2 -4
  133. package/dist/set-props-and-env.d.ts +1 -1
  134. package/dist/stitch-frames-to-video.d.ts +32 -11
  135. package/dist/stitch-frames-to-video.js +121 -99
  136. package/dist/stringify-ffmpeg-filter.d.ts +2 -2
  137. package/dist/symbolicate-stacktrace.d.ts +16 -3
  138. package/dist/symbolicate-stacktrace.js +49 -24
  139. package/dist/take-frame-and-compose.d.ts +0 -1
  140. package/dist/truthy.d.ts +1 -1
  141. package/dist/try-to-extract-frame-of-video-fast.d.ts +12 -0
  142. package/dist/try-to-extract-frame-of-video-fast.js +55 -0
  143. package/dist/types.d.ts +2 -2
  144. package/dist/validate-ffmpeg.d.ts +7 -0
  145. package/dist/validate-ffmpeg.js +77 -0
  146. package/dist/validate-opengl-renderer.d.ts +1 -1
  147. package/dist/warn-about-ffmpeg-version.d.ts +5 -0
  148. package/dist/warn-about-ffmpeg-version.js +37 -0
  149. package/package.json +11 -11
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.stitchFramesToVideo = void 0;
29
+ exports.stitchFramesToVideo = exports.internalStitchFramesToVideo = void 0;
30
30
  const node_fs_1 = __importStar(require("node:fs"));
31
31
  const node_path_1 = __importDefault(require("node:path"));
32
32
  const remotion_1 = require("remotion");
@@ -100,101 +100,97 @@ const getAssetsData = async ({ assets, onDownload, fps, expectedFrames, verbose,
100
100
  });
101
101
  return outName;
102
102
  };
103
- const spawnFfmpeg = async (options, remotionRoot) => {
104
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12;
105
- remotion_1.Internals.validateDimension(options.height, 'height', 'passed to `stitchFramesToVideo()`');
106
- remotion_1.Internals.validateDimension(options.width, 'width', 'passed to `stitchFramesToVideo()`');
107
- const codec = (_a = options.codec) !== null && _a !== void 0 ? _a : codec_1.DEFAULT_CODEC;
103
+ const innerStitchFramesToVideo = async ({ assetsInfo, audioBitrate, audioCodec, cancelSignal, codec, crf, dir, enforceAudioTrack, ffmpegOverride, force, fps, height, indent, muted, onDownload, outputLocation, pixelFormat, preEncodedFileLocation, preferLossless, proResProfile, verbose, videoBitrate, width, numberOfGifLoops, onProgress, }, remotionRoot) => {
104
+ var _a;
105
+ remotion_1.Internals.validateDimension(height, 'height', 'passed to `stitchFramesToVideo()`');
106
+ remotion_1.Internals.validateDimension(width, 'width', 'passed to `stitchFramesToVideo()`');
108
107
  (0, validate_even_dimensions_with_codec_1.validateEvenDimensionsWithCodec)({
109
- width: options.width,
110
- height: options.height,
108
+ width,
109
+ height,
111
110
  codec,
112
111
  scale: 1,
113
112
  });
114
113
  (0, prores_profile_1.validateSelectedCodecAndProResCombination)({
115
114
  codec,
116
- proResProfile: options.proResProfile,
115
+ proResProfile,
117
116
  });
118
- (0, validate_videobitrate_1.validateBitrate)(options.audioBitrate, 'audioBitrate');
119
- (0, validate_videobitrate_1.validateBitrate)(options.videoBitrate, 'videoBitrate');
120
- remotion_1.Internals.validateFps(options.fps, 'in `stitchFramesToVideo()`', false);
121
- const pixelFormat = (_b = options.pixelFormat) !== null && _b !== void 0 ? _b : pixel_format_1.DEFAULT_PIXEL_FORMAT;
117
+ (0, validate_videobitrate_1.validateBitrate)(audioBitrate, 'audioBitrate');
118
+ (0, validate_videobitrate_1.validateBitrate)(videoBitrate, 'videoBitrate');
119
+ remotion_1.Internals.validateFps(fps, 'in `stitchFramesToVideo()`', false);
122
120
  const encoderName = (0, get_codec_name_1.getCodecName)(codec);
123
- const proResProfileName = (0, get_prores_profile_name_1.getProResProfileName)(codec, options.proResProfile);
121
+ const proResProfileName = (0, get_prores_profile_name_1.getProResProfileName)(codec, proResProfile);
124
122
  const mediaSupport = (0, codec_supports_media_1.codecSupportsMedia)(codec);
125
123
  const shouldRenderAudio = mediaSupport.audio &&
126
- (options.assetsInfo.assets.flat(1).length > 0 ||
127
- options.enforceAudioTrack) &&
128
- !options.muted;
124
+ (assetsInfo.assets.flat(1).length > 0 || enforceAudioTrack) &&
125
+ !muted;
129
126
  const shouldRenderVideo = mediaSupport.video;
130
127
  if (!shouldRenderAudio && !shouldRenderVideo) {
131
128
  throw new Error('The output format has neither audio nor video. This can happen if you are rendering an audio codec and the output file has no audio or the muted flag was passed.');
132
129
  }
133
130
  // Explanation: https://github.com/remotion-dev/remotion/issues/1647
134
- const resolvedAudioCodec = ((_c = options.internalOptions) === null || _c === void 0 ? void 0 : _c.preferLossless)
131
+ const resolvedAudioCodec = preferLossless
135
132
  ? (0, audio_codec_1.getDefaultAudioCodec)({ codec, preferLossless: true })
136
- : (_d = options.audioCodec) !== null && _d !== void 0 ? _d : (0, audio_codec_1.getDefaultAudioCodec)({ codec, preferLossless: false });
137
- const tempFile = options.outputLocation
133
+ : audioCodec !== null && audioCodec !== void 0 ? audioCodec : (0, audio_codec_1.getDefaultAudioCodec)({ codec, preferLossless: false });
134
+ const tempFile = outputLocation
138
135
  ? null
139
- : node_path_1.default.join(options.assetsInfo.downloadMap.stitchFrames, `out.${(0, get_extension_from_codec_1.getFileExtensionFromCodec)(codec, resolvedAudioCodec)}`);
136
+ : node_path_1.default.join(assetsInfo.downloadMap.stitchFrames, `out.${(0, get_extension_from_codec_1.getFileExtensionFromCodec)(codec, resolvedAudioCodec)}`);
140
137
  logger_1.Log.verboseAdvanced({
141
- indent: (_f = (_e = options.internalOptions) === null || _e === void 0 ? void 0 : _e.indent) !== null && _f !== void 0 ? _f : false,
142
- logLevel: options.verbose ? 'verbose' : 'info',
143
- tag: 'encoder',
138
+ indent,
139
+ logLevel: verbose ? 'verbose' : 'info',
140
+ tag: 'stitchFramesToVideo()',
144
141
  }, 'encoder', encoderName);
145
142
  logger_1.Log.verboseAdvanced({
146
- indent: (_h = (_g = options.internalOptions) === null || _g === void 0 ? void 0 : _g.indent) !== null && _h !== void 0 ? _h : false,
147
- logLevel: options.verbose ? 'verbose' : 'info',
148
- tag: 'encoder',
143
+ indent,
144
+ logLevel: verbose ? 'verbose' : 'info',
145
+ tag: 'stitchFramesToVideo()',
149
146
  }, 'audioCodec', resolvedAudioCodec);
150
147
  logger_1.Log.verboseAdvanced({
151
- indent: (_k = (_j = options.internalOptions) === null || _j === void 0 ? void 0 : _j.indent) !== null && _k !== void 0 ? _k : false,
152
- logLevel: options.verbose ? 'verbose' : 'info',
153
- tag: 'encoder',
148
+ indent,
149
+ logLevel: verbose ? 'verbose' : 'info',
150
+ tag: 'stitchFramesToVideo()',
154
151
  }, 'pixelFormat', pixelFormat);
155
152
  logger_1.Log.verboseAdvanced({
156
- indent: (_m = (_l = options.internalOptions) === null || _l === void 0 ? void 0 : _l.indent) !== null && _m !== void 0 ? _m : false,
157
- logLevel: options.verbose ? 'verbose' : 'info',
158
- tag: 'encoder',
153
+ indent,
154
+ logLevel: verbose ? 'verbose' : 'info',
155
+ tag: 'stitchFramesToVideo()',
159
156
  }, 'codec', codec);
160
157
  logger_1.Log.verboseAdvanced({
161
- indent: (_p = (_o = options.internalOptions) === null || _o === void 0 ? void 0 : _o.indent) !== null && _p !== void 0 ? _p : false,
162
- logLevel: options.verbose ? 'verbose' : 'info',
163
- tag: 'encoder',
158
+ indent,
159
+ logLevel: verbose ? 'verbose' : 'info',
160
+ tag: 'stitchFramesToVideo()',
164
161
  }, 'shouldRenderAudio', shouldRenderAudio);
165
162
  logger_1.Log.verboseAdvanced({
166
- indent: (_r = (_q = options.internalOptions) === null || _q === void 0 ? void 0 : _q.indent) !== null && _r !== void 0 ? _r : false,
167
- logLevel: options.verbose ? 'verbose' : 'info',
168
- tag: 'encoder',
163
+ indent,
164
+ logLevel: verbose ? 'verbose' : 'info',
165
+ tag: 'stitchFramesToVideo()',
169
166
  }, 'shouldRenderVideo', shouldRenderVideo);
170
167
  logger_1.Log.verboseAdvanced({
171
- indent: (_t = (_s = options.internalOptions) === null || _s === void 0 ? void 0 : _s.indent) !== null && _t !== void 0 ? _t : false,
172
- logLevel: options.verbose ? 'verbose' : 'info',
173
- tag: 'encoder',
168
+ indent,
169
+ logLevel: verbose ? 'verbose' : 'info',
170
+ tag: 'stitchFramesToVideo()',
174
171
  }, 'proResProfileName', proResProfileName);
175
172
  (0, crf_1.validateQualitySettings)({
176
- crf: options.crf,
173
+ crf,
177
174
  codec,
178
- videoBitrate: options.videoBitrate,
175
+ videoBitrate,
179
176
  });
180
177
  (0, pixel_format_1.validateSelectedPixelFormatAndCodecCombination)(pixelFormat, codec);
181
- const expectedFrames = options.assetsInfo.assets.length;
178
+ const expectedFrames = assetsInfo.assets.length;
182
179
  const updateProgress = (preStitchProgress, muxProgress) => {
183
- var _a;
184
180
  const totalFrameProgress = 0.5 * preStitchProgress * expectedFrames + muxProgress * 0.5;
185
- (_a = options.onProgress) === null || _a === void 0 ? void 0 : _a.call(options, Math.round(totalFrameProgress));
181
+ onProgress === null || onProgress === void 0 ? void 0 : onProgress(Math.round(totalFrameProgress));
186
182
  };
187
183
  const audio = shouldRenderAudio
188
184
  ? await getAssetsData({
189
- assets: options.assetsInfo.assets,
190
- onDownload: options.onDownload,
191
- fps: options.fps,
185
+ assets: assetsInfo.assets,
186
+ onDownload,
187
+ fps,
192
188
  expectedFrames,
193
- verbose: (_u = options.verbose) !== null && _u !== void 0 ? _u : false,
189
+ verbose,
194
190
  onProgress: (prog) => updateProgress(prog, 0),
195
- downloadMap: options.assetsInfo.downloadMap,
191
+ downloadMap: assetsInfo.downloadMap,
196
192
  remotionRoot,
197
- indent: (_w = (_v = options.internalOptions) === null || _v === void 0 ? void 0 : _v.indent) !== null && _w !== void 0 ? _w : false,
193
+ indent,
198
194
  })
199
195
  : null;
200
196
  if (mediaSupport.audio && !mediaSupport.video) {
@@ -208,15 +204,15 @@ const spawnFfmpeg = async (options, remotionRoot) => {
208
204
  (0, audio_codec_1.mapAudioCodecToFfmpegAudioCodecName)(resolvedAudioCodec),
209
205
  // Set bitrate up to 320k, for aac it might effectively be lower
210
206
  '-b:a',
211
- (_x = options.audioBitrate) !== null && _x !== void 0 ? _x : '320k',
212
- options.force ? '-y' : null,
213
- (_y = options.outputLocation) !== null && _y !== void 0 ? _y : tempFile,
207
+ audioBitrate !== null && audioBitrate !== void 0 ? audioBitrate : '320k',
208
+ force ? '-y' : null,
209
+ outputLocation !== null && outputLocation !== void 0 ? outputLocation : tempFile,
214
210
  ].filter(remotion_1.Internals.truthy));
215
- (_z = options.cancelSignal) === null || _z === void 0 ? void 0 : _z.call(options, () => {
211
+ cancelSignal === null || cancelSignal === void 0 ? void 0 : cancelSignal(() => {
216
212
  ffmpegTask.kill();
217
213
  });
218
214
  await ffmpegTask;
219
- (_0 = options.onProgress) === null || _0 === void 0 ? void 0 : _0.call(options, expectedFrames);
215
+ onProgress === null || onProgress === void 0 ? void 0 : onProgress(expectedFrames);
220
216
  if (audio) {
221
217
  (0, delete_directory_1.deleteDirectory)(node_path_1.default.dirname(audio));
222
218
  }
@@ -233,33 +229,30 @@ const spawnFfmpeg = async (options, remotionRoot) => {
233
229
  resolve(null);
234
230
  }
235
231
  });
236
- (0, delete_directory_1.deleteDirectory)(options.assetsInfo.downloadMap.stitchFrames);
232
+ (0, delete_directory_1.deleteDirectory)(assetsInfo.downloadMap.stitchFrames);
237
233
  return {
238
234
  getLogs: () => '',
239
235
  task: Promise.resolve(file),
240
236
  };
241
237
  }
242
238
  const ffmpegArgs = [
243
- ...(((_1 = options.internalOptions) === null || _1 === void 0 ? void 0 : _1.preEncodedFileLocation)
244
- ? [['-i', (_2 = options.internalOptions) === null || _2 === void 0 ? void 0 : _2.preEncodedFileLocation]]
239
+ ...(preEncodedFileLocation
240
+ ? [['-i', preEncodedFileLocation]]
245
241
  : [
246
- ['-r', String(options.fps)],
242
+ ['-r', String(fps)],
247
243
  ['-f', 'image2'],
248
- ['-s', `${options.width}x${options.height}`],
249
- ['-start_number', String(options.assetsInfo.firstFrameIndex)],
250
- ['-i', options.assetsInfo.imageSequenceName],
244
+ ['-s', `${width}x${height}`],
245
+ ['-start_number', String(assetsInfo.firstFrameIndex)],
246
+ ['-i', assetsInfo.imageSequenceName],
251
247
  ]),
252
248
  audio ? ['-i', audio] : null,
253
- ((_3 = options.numberOfGifLoops) !== null && _3 !== void 0 ? _3 : null) === null
249
+ numberOfGifLoops === null
254
250
  ? null
255
- : [
256
- '-loop',
257
- (0, convert_number_of_gif_loops_to_ffmpeg_1.convertNumberOfGifLoopsToFfmpegSyntax)((_4 = options.numberOfGifLoops) !== null && _4 !== void 0 ? _4 : null),
258
- ],
251
+ : ['-loop', (0, convert_number_of_gif_loops_to_ffmpeg_1.convertNumberOfGifLoopsToFfmpegSyntax)(numberOfGifLoops)],
259
252
  // -c:v is the same as -vcodec as -codec:video
260
253
  // and specified the video codec.
261
254
  ['-c:v', encoderName],
262
- ...(((_5 = options.internalOptions) === null || _5 === void 0 ? void 0 : _5.preEncodedFileLocation)
255
+ ...(preEncodedFileLocation
263
256
  ? []
264
257
  : [
265
258
  proResProfileName ? ['-profile:v', proResProfileName] : null,
@@ -268,8 +261,8 @@ const spawnFfmpeg = async (options, remotionRoot) => {
268
261
  // transparent WebM generation doesn't work
269
262
  pixelFormat === 'yuva420p' ? ['-auto-alt-ref', '0'] : null,
270
263
  ...(0, crf_1.validateQualitySettings)({
271
- crf: options.crf,
272
- videoBitrate: options.videoBitrate,
264
+ crf,
265
+ videoBitrate,
273
266
  codec,
274
267
  }),
275
268
  ]),
@@ -278,7 +271,7 @@ const spawnFfmpeg = async (options, remotionRoot) => {
278
271
  ? ['-c:a', (0, audio_codec_1.mapAudioCodecToFfmpegAudioCodecName)(resolvedAudioCodec)]
279
272
  : null,
280
273
  // Set max bitrate up to 1024kbps, will choose lower if that's too much
281
- resolvedAudioCodec ? ['-b:a', options.audioBitrate || '512K'] : null,
274
+ resolvedAudioCodec ? ['-b:a', audioBitrate || '512K'] : null,
282
275
  // Ignore metadata that may come from remote media
283
276
  ['-map_metadata', '-1'],
284
277
  [
@@ -286,36 +279,36 @@ const spawnFfmpeg = async (options, remotionRoot) => {
286
279
  `comment=` +
287
280
  [`Made with Remotion`, packageJson ? packageJson.version : null].join(' '),
288
281
  ],
289
- options.force ? '-y' : null,
290
- (_6 = options.outputLocation) !== null && _6 !== void 0 ? _6 : tempFile,
282
+ force ? '-y' : null,
283
+ outputLocation !== null && outputLocation !== void 0 ? outputLocation : tempFile,
291
284
  ];
292
285
  const ffmpegString = ffmpegArgs.flat(2).filter(Boolean);
293
- const finalFfmpegString = options.ffmpegOverride
294
- ? options.ffmpegOverride({ type: 'stitcher', args: ffmpegString })
286
+ const finalFfmpegString = ffmpegOverride
287
+ ? ffmpegOverride({ type: 'stitcher', args: ffmpegString })
295
288
  : ffmpegString;
296
289
  logger_1.Log.verboseAdvanced({
297
- indent: (_8 = (_7 = options.internalOptions) === null || _7 === void 0 ? void 0 : _7.indent) !== null && _8 !== void 0 ? _8 : false,
298
- logLevel: options.verbose ? 'verbose' : 'info',
299
- tag: 'encoder',
290
+ indent: indent !== null && indent !== void 0 ? indent : false,
291
+ logLevel: verbose ? 'verbose' : 'info',
292
+ tag: 'stitchFramesToVideo()',
300
293
  }, 'Generated final FFMPEG command:');
301
294
  logger_1.Log.verboseAdvanced({
302
- indent: (_10 = (_9 = options.internalOptions) === null || _9 === void 0 ? void 0 : _9.indent) !== null && _10 !== void 0 ? _10 : false,
303
- logLevel: options.verbose ? 'verbose' : 'info',
304
- tag: 'encoder',
295
+ indent,
296
+ logLevel: verbose ? 'verbose' : 'info',
297
+ tag: 'stitchFramesToVideo()',
305
298
  }, finalFfmpegString.join(' '));
306
299
  const task = (0, call_ffmpeg_1.callFf)('ffmpeg', finalFfmpegString, {
307
- cwd: options.dir,
300
+ cwd: dir,
308
301
  });
309
- (_11 = options.cancelSignal) === null || _11 === void 0 ? void 0 : _11.call(options, () => {
302
+ cancelSignal === null || cancelSignal === void 0 ? void 0 : cancelSignal(() => {
310
303
  task.kill();
311
304
  });
312
305
  let ffmpegOutput = '';
313
306
  let isFinished = false;
314
- (_12 = task.stderr) === null || _12 === void 0 ? void 0 : _12.on('data', (data) => {
307
+ (_a = task.stderr) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
315
308
  var _a;
316
309
  const str = data.toString();
317
310
  ffmpegOutput += str;
318
- if (options.onProgress) {
311
+ if (onProgress) {
319
312
  const parsed = (0, parse_ffmpeg_progress_1.parseFfmpegProgress)(str);
320
313
  // FFMPEG bug: In some cases, FFMPEG does hang after it is finished with it's job
321
314
  // Example repo: https://github.com/JonnyBurger/ffmpeg-repro (access can be given upon request)
@@ -335,9 +328,9 @@ const spawnFfmpeg = async (options, remotionRoot) => {
335
328
  });
336
329
  return {
337
330
  task: task.then(() => {
338
- (0, delete_directory_1.deleteDirectory)(options.assetsInfo.downloadMap.audioPreprocessing);
331
+ (0, delete_directory_1.deleteDirectory)(assetsInfo.downloadMap.audioPreprocessing);
339
332
  if (tempFile === null) {
340
- (0, delete_directory_1.deleteDirectory)(options.assetsInfo.downloadMap.stitchFrames);
333
+ (0, delete_directory_1.deleteDirectory)(assetsInfo.downloadMap.stitchFrames);
341
334
  return null;
342
335
  }
343
336
  return node_fs_1.promises
@@ -346,7 +339,7 @@ const spawnFfmpeg = async (options, remotionRoot) => {
346
339
  return Promise.all([
347
340
  file,
348
341
  (0, delete_directory_1.deleteDirectory)(node_path_1.default.dirname(tempFile)),
349
- (0, delete_directory_1.deleteDirectory)(options.assetsInfo.downloadMap.stitchFrames),
342
+ (0, delete_directory_1.deleteDirectory)(assetsInfo.downloadMap.stitchFrames),
350
343
  ]);
351
344
  })
352
345
  .then(([file]) => file);
@@ -354,18 +347,13 @@ const spawnFfmpeg = async (options, remotionRoot) => {
354
347
  getLogs: () => ffmpegOutput,
355
348
  };
356
349
  };
357
- /**
358
- * @description Takes a series of images and audio information generated by renderFrames() and encodes it to a video.
359
- * @see [Documentation](https://www.remotion.dev/docs/renderer/stitch-frames-to-video)
360
- */
361
- const stitchFramesToVideo = async (options) => {
362
- var _a, _b;
350
+ const internalStitchFramesToVideo = async (options) => {
363
351
  const remotionRoot = (0, find_closest_package_json_1.findRemotionRoot)();
364
- const { task, getLogs } = await spawnFfmpeg(options, remotionRoot);
352
+ (0, does_have_m2_bug_1.warnAboutM2Bug)(options.codec, options.pixelFormat);
353
+ const { task, getLogs } = await innerStitchFramesToVideo(options, remotionRoot);
365
354
  const happyPath = task.catch(() => {
366
355
  throw new Error(getLogs());
367
356
  });
368
- (0, does_have_m2_bug_1.warnAboutM2Bug)((_a = options.codec) !== null && _a !== void 0 ? _a : null, (_b = options.pixelFormat) !== null && _b !== void 0 ? _b : null);
369
357
  return Promise.race([
370
358
  happyPath,
371
359
  new Promise((_resolve, reject) => {
@@ -376,4 +364,38 @@ const stitchFramesToVideo = async (options) => {
376
364
  }),
377
365
  ]);
378
366
  };
367
+ exports.internalStitchFramesToVideo = internalStitchFramesToVideo;
368
+ /**
369
+ * @description Takes a series of images and audio information generated by renderFrames() and encodes it to a video.
370
+ * @see [Documentation](https://www.remotion.dev/docs/renderer/stitch-frames-to-video)
371
+ */
372
+ const stitchFramesToVideo = ({ assetsInfo, force, fps, height, width, audioBitrate, audioCodec, cancelSignal, codec, crf, dir, enforceAudioTrack, ffmpegOverride, muted, numberOfGifLoops, onDownload, onProgress, outputLocation, pixelFormat, proResProfile, verbose, videoBitrate, }) => {
373
+ return (0, exports.internalStitchFramesToVideo)({
374
+ assetsInfo,
375
+ audioBitrate: audioBitrate !== null && audioBitrate !== void 0 ? audioBitrate : null,
376
+ audioCodec: audioCodec !== null && audioCodec !== void 0 ? audioCodec : null,
377
+ cancelSignal: cancelSignal !== null && cancelSignal !== void 0 ? cancelSignal : null,
378
+ codec: codec !== null && codec !== void 0 ? codec : codec_1.DEFAULT_CODEC,
379
+ crf: crf !== null && crf !== void 0 ? crf : null,
380
+ dir,
381
+ enforceAudioTrack: enforceAudioTrack !== null && enforceAudioTrack !== void 0 ? enforceAudioTrack : false,
382
+ ffmpegOverride: ffmpegOverride !== null && ffmpegOverride !== void 0 ? ffmpegOverride : null,
383
+ force,
384
+ fps,
385
+ height,
386
+ indent: false,
387
+ muted: muted !== null && muted !== void 0 ? muted : false,
388
+ numberOfGifLoops: numberOfGifLoops !== null && numberOfGifLoops !== void 0 ? numberOfGifLoops : null,
389
+ onDownload: onDownload !== null && onDownload !== void 0 ? onDownload : undefined,
390
+ onProgress,
391
+ outputLocation: outputLocation !== null && outputLocation !== void 0 ? outputLocation : null,
392
+ pixelFormat: pixelFormat !== null && pixelFormat !== void 0 ? pixelFormat : pixel_format_1.DEFAULT_PIXEL_FORMAT,
393
+ proResProfile,
394
+ verbose: verbose !== null && verbose !== void 0 ? verbose : false,
395
+ videoBitrate: videoBitrate !== null && videoBitrate !== void 0 ? videoBitrate : null,
396
+ width,
397
+ preEncodedFileLocation: null,
398
+ preferLossless: false,
399
+ });
400
+ };
379
401
  exports.stitchFramesToVideo = stitchFramesToVideo;
@@ -1,8 +1,8 @@
1
1
  import type { AssetVolume } from './assets/types';
2
- export declare type FilterWithoutPaddingApplied = ProcessedTrack & {
2
+ export type FilterWithoutPaddingApplied = ProcessedTrack & {
3
3
  filter: string;
4
4
  };
5
- export declare type ProcessedTrack = {
5
+ export type ProcessedTrack = {
6
6
  pad_start: string | null;
7
7
  pad_end: string | null;
8
8
  };
@@ -1,15 +1,28 @@
1
+ import type { BasicSourceMapConsumer, IndexedSourceMapConsumer } from 'source-map';
2
+ import { SourceMapConsumer } from 'source-map';
1
3
  import type { UnsymbolicatedStackFrame } from './parse-browser-error-stack';
2
- declare type ScriptLine = {
4
+ type ScriptLine = {
3
5
  lineNumber: number;
4
6
  content: string;
5
7
  highlight: boolean;
6
8
  };
7
- export declare type SymbolicatedStackFrame = {
9
+ export type SymbolicatedStackFrame = {
8
10
  originalFunctionName: string | null;
9
11
  originalFileName: string | null;
10
12
  originalLineNumber: number | null;
11
13
  originalColumnNumber: number | null;
12
14
  originalScriptCode: ScriptLine[] | null;
13
15
  };
14
- export declare const symbolicateStackTrace: (frames: UnsymbolicatedStackFrame[]) => Promise<SymbolicatedStackFrame[]>;
16
+ export declare const symbolicateStackTraceFromRemoteFrames: (frames: UnsymbolicatedStackFrame[]) => Promise<SymbolicatedStackFrame[]>;
17
+ export declare const symbolicateFromSources: (frames: UnsymbolicatedStackFrame[], mapValues: Record<string, SourceMapConsumer | null>) => SymbolicatedStackFrame[];
18
+ export declare const symbolicateStackFrame: (frame: UnsymbolicatedStackFrame, map: SourceMapConsumer) => {
19
+ originalColumnNumber: number | null;
20
+ originalFileName: string | null;
21
+ originalFunctionName: string | null;
22
+ originalLineNumber: number | null;
23
+ originalScriptCode: ScriptLine[] | null;
24
+ };
25
+ export declare const getSourceMapFromRemoteFile: (fileName: string) => Promise<IndexedSourceMapConsumer | null>;
26
+ export declare const getSourceMapFromLocalFile: (fileName: string) => Promise<IndexedSourceMapConsumer | null>;
27
+ export type AnySourceMapConsumer = BasicSourceMapConsumer | IndexedSourceMapConsumer;
15
28
  export {};
@@ -1,6 +1,11 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.symbolicateStackTrace = void 0;
6
+ exports.getSourceMapFromLocalFile = exports.getSourceMapFromRemoteFile = exports.symbolicateStackFrame = exports.symbolicateFromSources = exports.symbolicateStackTraceFromRemoteFrames = void 0;
7
+ const fs_1 = require("fs");
8
+ const path_1 = __importDefault(require("path"));
4
9
  const source_map_1 = require("source-map");
5
10
  const read_file_1 = require("./assets/read-file");
6
11
  const truthy_1 = require("./truthy");
@@ -19,7 +24,7 @@ function extractSourceMapUrl(fileContents) {
19
24
  }
20
25
  return match[1].toString();
21
26
  }
22
- async function getSourceMap(fileUri, fileContents) {
27
+ const getSourceMap = async (filePath, fileContents, type) => {
23
28
  const sm = extractSourceMapUrl(fileContents);
24
29
  if (sm === null) {
25
30
  return null;
@@ -33,11 +38,16 @@ async function getSourceMap(fileUri, fileContents) {
33
38
  const converted = window.atob(sm.substring(match2[0].length));
34
39
  return new source_map_1.SourceMapConsumer(JSON.parse(converted));
35
40
  }
36
- const index = fileUri.lastIndexOf('/');
37
- const url = fileUri.substring(0, index + 1) + sm;
41
+ if (type === 'local') {
42
+ // Find adjacent file: bundle.js -> bundle.js.map
43
+ const newFilePath = path_1.default.join(path_1.default.dirname(filePath), sm);
44
+ return new source_map_1.SourceMapConsumer((0, fs_1.readFileSync)(newFilePath, 'utf8'));
45
+ }
46
+ const index = filePath.lastIndexOf('/');
47
+ const url = filePath.substring(0, index + 1) + sm;
38
48
  const obj = await fetchUrl(url);
39
49
  return new source_map_1.SourceMapConsumer(obj);
40
- }
50
+ };
41
51
  const fetchUrl = async (url) => {
42
52
  const res = await (0, read_file_1.readFile)(url);
43
53
  return new Promise((resolve, reject) => {
@@ -69,42 +79,57 @@ const getOriginalPosition = (source_map, line, column) => {
69
79
  });
70
80
  return { line: result.line, column: result.column, source: result.source };
71
81
  };
72
- const symbolicateStackTrace = async (frames) => {
82
+ const symbolicateStackTraceFromRemoteFrames = async (frames) => {
73
83
  const uniqueFileNames = [
74
84
  ...new Set(frames
75
85
  .map((f) => f.fileName)
76
86
  .filter((f) => f.startsWith('http://') || f.startsWith('https://'))
77
87
  .filter(truthy_1.truthy)),
78
88
  ];
79
- const maps = await Promise.all(uniqueFileNames.map(async (fileName) => {
80
- const fileContents = await fetchUrl(fileName);
81
- return getSourceMap(fileName, fileContents);
89
+ const maps = await Promise.all(uniqueFileNames.map((fileName) => {
90
+ return (0, exports.getSourceMapFromRemoteFile)(fileName);
82
91
  }));
83
92
  const mapValues = {};
84
93
  for (let i = 0; i < uniqueFileNames.length; i++) {
85
94
  mapValues[uniqueFileNames[i]] = maps[i];
86
95
  }
96
+ return (0, exports.symbolicateFromSources)(frames, mapValues);
97
+ };
98
+ exports.symbolicateStackTraceFromRemoteFrames = symbolicateStackTraceFromRemoteFrames;
99
+ const symbolicateFromSources = (frames, mapValues) => {
87
100
  return frames
88
101
  .map((frame) => {
89
102
  const map = mapValues[frame.fileName];
90
103
  if (!map) {
91
104
  return null;
92
105
  }
93
- const pos = getOriginalPosition(map, frame.lineNumber, frame.columnNumber);
94
- const { functionName } = frame;
95
- let hasSource = null;
96
- hasSource = pos.source ? map.sourceContentFor(pos.source, false) : null;
97
- const scriptCode = hasSource && pos.line
98
- ? getLinesAround(pos.line, 3, hasSource.split('\n'))
99
- : null;
100
- return {
101
- originalColumnNumber: pos.column,
102
- originalFileName: pos.source,
103
- originalFunctionName: functionName,
104
- originalLineNumber: pos.line ? pos.line : null,
105
- originalScriptCode: scriptCode,
106
- };
106
+ return (0, exports.symbolicateStackFrame)(frame, map);
107
107
  })
108
108
  .filter(truthy_1.truthy);
109
109
  };
110
- exports.symbolicateStackTrace = symbolicateStackTrace;
110
+ exports.symbolicateFromSources = symbolicateFromSources;
111
+ const symbolicateStackFrame = (frame, map) => {
112
+ const pos = getOriginalPosition(map, frame.lineNumber, frame.columnNumber);
113
+ const hasSource = pos.source ? map.sourceContentFor(pos.source, false) : null;
114
+ const scriptCode = hasSource && pos.line
115
+ ? getLinesAround(pos.line, 3, hasSource.split('\n'))
116
+ : null;
117
+ return {
118
+ originalColumnNumber: pos.column,
119
+ originalFileName: pos.source,
120
+ originalFunctionName: frame.functionName,
121
+ originalLineNumber: pos.line,
122
+ originalScriptCode: scriptCode,
123
+ };
124
+ };
125
+ exports.symbolicateStackFrame = symbolicateStackFrame;
126
+ const getSourceMapFromRemoteFile = async (fileName) => {
127
+ const fileContents = await fetchUrl(fileName);
128
+ return getSourceMap(fileName, fileContents, 'remote');
129
+ };
130
+ exports.getSourceMapFromRemoteFile = getSourceMapFromRemoteFile;
131
+ const getSourceMapFromLocalFile = (fileName) => {
132
+ const fileContents = (0, fs_1.readFileSync)(fileName, 'utf8');
133
+ return getSourceMap(fileName, fileContents, 'local');
134
+ };
135
+ exports.getSourceMapFromLocalFile = getSourceMapFromLocalFile;
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import type { TAsset } from 'remotion';
3
2
  import type { DownloadMap } from './assets/download-map';
4
3
  import type { Page } from './browser/BrowserPage';
package/dist/truthy.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- declare type Truthy<T> = T extends false | '' | 0 | null | undefined ? never : T;
1
+ type Truthy<T> = T extends false | '' | 0 | null | undefined ? never : T;
2
2
  export declare function truthy<T>(value: T): value is Truthy<T>;
3
3
  export {};
@@ -0,0 +1,12 @@
1
+ import type { OffthreadVideoImageFormat } from 'remotion';
2
+ import type { NeedsResize, SpecialVCodecForTransparency } from './assets/download-map';
3
+ import type { FfmpegExecutable } from './ffmpeg-executable';
4
+ export declare const tryToExtractFrameOfVideoFast: ({ ffmpegExecutable, remotionRoot, specialVCodecForTransparency, imageFormat, needsResize, src, actualOffset, }: {
5
+ ffmpegExecutable: FfmpegExecutable;
6
+ remotionRoot: string;
7
+ imageFormat: OffthreadVideoImageFormat;
8
+ needsResize: NeedsResize;
9
+ src: string;
10
+ specialVCodecForTransparency: SpecialVCodecForTransparency;
11
+ actualOffset: string;
12
+ }) => Promise<readonly [string, Buffer]>;
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.tryToExtractFrameOfVideoFast = void 0;
7
+ const execa_1 = __importDefault(require("execa"));
8
+ const determine_resize_params_1 = require("./determine-resize-params");
9
+ const determine_vcodec_ffmpeg_flags_1 = require("./determine-vcodec-ffmpeg-flags");
10
+ const ffmpeg_flags_1 = require("./ffmpeg-flags");
11
+ const truthy_1 = require("./truthy");
12
+ const tryToExtractFrameOfVideoFast = async ({ ffmpegExecutable, remotionRoot, specialVCodecForTransparency, imageFormat, needsResize, src, actualOffset, }) => {
13
+ const { stdout, stderr } = (0, execa_1.default)(await (0, ffmpeg_flags_1.getExecutableBinary)(ffmpegExecutable, remotionRoot, 'ffmpeg'), [
14
+ '-ss',
15
+ actualOffset,
16
+ ...(0, determine_vcodec_ffmpeg_flags_1.determineVcodecFfmpegFlags)(specialVCodecForTransparency),
17
+ '-i',
18
+ src,
19
+ '-frames:v',
20
+ '1',
21
+ '-c:v',
22
+ imageFormat === 'jpeg' ? 'mjpeg' : 'png',
23
+ '-f',
24
+ 'image2pipe',
25
+ ...(0, determine_resize_params_1.determineResizeParams)(needsResize),
26
+ '-',
27
+ ].filter(truthy_1.truthy));
28
+ if (!stderr) {
29
+ throw new Error('unexpectedly did not get stderr');
30
+ }
31
+ if (!stdout) {
32
+ throw new Error('unexpectedly did not get stdout');
33
+ }
34
+ const stderrChunks = [];
35
+ const stdoutChunks = [];
36
+ const stdErrString = new Promise((resolve, reject) => {
37
+ stderr.on('data', (d) => stderrChunks.push(d));
38
+ stderr.on('error', (err) => reject(err));
39
+ stderr.on('end', () => resolve(Buffer.concat(stderrChunks).toString('utf-8')));
40
+ });
41
+ const stdoutChunk = new Promise((resolve, reject) => {
42
+ stdout.on('data', (d) => {
43
+ stdoutChunks.push(d);
44
+ });
45
+ stdout.on('error', (err) => {
46
+ reject(err);
47
+ });
48
+ stdout.on('end', () => {
49
+ resolve(Buffer.concat(stdoutChunks));
50
+ });
51
+ });
52
+ const [stdErr, stdoutBuffer] = await Promise.all([stdErrString, stdoutChunk]);
53
+ return [stdErr, stdoutBuffer];
54
+ };
55
+ exports.tryToExtractFrameOfVideoFast = tryToExtractFrameOfVideoFast;
package/dist/types.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import type { RenderAssetInfo } from './assets/download-map';
2
- export declare type RenderFramesOutput = {
2
+ export type RenderFramesOutput = {
3
3
  frameCount: number;
4
4
  assetsInfo: RenderAssetInfo;
5
5
  };
6
- export declare type OnStartData = {
6
+ export type OnStartData = {
7
7
  frameCount: number;
8
8
  };
@@ -0,0 +1,7 @@
1
+ export declare const customExecutableExists: (localExecutable: string) => boolean;
2
+ export declare const binaryExists: (name: 'ffmpeg' | 'ffprobe') => boolean;
3
+ export declare const checkAndValidateFfmpegVersion: (options: {
4
+ ffmpegExecutable: string | null;
5
+ remotionRoot: string;
6
+ }) => Promise<void>;
7
+ export declare const validateFfmpeg: (customFfmpegBinary: string | null, remotionRoot: string, binary: 'ffmpeg' | 'ffprobe') => Promise<void>;