@remotion/renderer 4.0.501 → 4.0.503

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 (39) hide show
  1. package/dist/assets/calculate-asset-positions.d.ts +1 -1
  2. package/dist/assets/calculate-asset-positions.js +7 -1
  3. package/dist/browser/BrowserFetcher.js +61 -48
  4. package/dist/browser/browser-download-lock.d.ts +1 -0
  5. package/dist/browser/browser-download-lock.js +161 -0
  6. package/dist/client.d.ts +42 -5
  7. package/dist/client.js +6 -1
  8. package/dist/combine-chunks.d.ts +2 -2
  9. package/dist/combine-chunks.js +1 -1
  10. package/dist/create-audio.js +1 -1
  11. package/dist/esm/client.mjs +907 -692
  12. package/dist/esm/index.mjs +430 -181
  13. package/dist/esm/pure.mjs +5 -4
  14. package/dist/frame-range.d.ts +10 -1
  15. package/dist/frame-range.js +60 -36
  16. package/dist/get-duration-from-frame-range.d.ts +2 -1
  17. package/dist/get-duration-from-frame-range.js +7 -4
  18. package/dist/get-frame-to-render.d.ts +2 -1
  19. package/dist/get-frame-to-render.js +21 -5
  20. package/dist/index.d.ts +12 -3
  21. package/dist/index.js +9 -1
  22. package/dist/options/default-editor.d.ts +28 -0
  23. package/dist/options/default-editor.js +84 -0
  24. package/dist/options/frames.d.ts +4 -4
  25. package/dist/options/frames.js +51 -8
  26. package/dist/options/index.d.ts +40 -5
  27. package/dist/options/index.js +4 -0
  28. package/dist/options/rspack.d.ts +2 -2
  29. package/dist/options/rspack.js +3 -4
  30. package/dist/options/skip-skills.d.ts +19 -0
  31. package/dist/options/skip-skills.js +29 -0
  32. package/dist/pure.d.ts +1 -1
  33. package/dist/render-frame-with-option-to-reject.js +2 -1
  34. package/dist/render-frames.d.ts +5 -1
  35. package/dist/render-frames.js +42 -7
  36. package/dist/render-media.js +11 -5
  37. package/dist/validate-selected-frames.d.ts +4 -0
  38. package/dist/validate-selected-frames.js +34 -0
  39. package/package.json +13 -13
@@ -1,3 +1,3 @@
1
1
  import type { AudioOrVideoAsset } from 'remotion/no-react';
2
2
  import type { Assets } from './types';
3
- export declare const calculateAssetPositions: (frames: AudioOrVideoAsset[][]) => Assets;
3
+ export declare const calculateAssetPositions: (frames: AudioOrVideoAsset[][], sourceFrames?: number[]) => Assets;
@@ -40,7 +40,7 @@ const indexUncompressedAssets = (renderAssets) => {
40
40
  }
41
41
  return assetsByReference;
42
42
  };
43
- const calculateAssetPositions = (frames) => {
43
+ const calculateAssetPositions = (frames, sourceFrames = frames.map((_, index) => index)) => {
44
44
  const assets = [];
45
45
  // Assets that have started but not yet ended, keyed by asset id.
46
46
  // Since assets are deduplicated by id within a frame, at most one
@@ -49,6 +49,12 @@ const calculateAssetPositions = (frames) => {
49
49
  const flattened = frames.flat(1);
50
50
  const uncompressedAssets = indexUncompressedAssets(flattened);
51
51
  for (let frame = 0; frame < frames.length; frame++) {
52
+ if (frame > 0 && sourceFrames[frame] !== sourceFrames[frame - 1] + 1) {
53
+ for (const openAsset of openAssets.values()) {
54
+ openAsset.duration = frame - openAsset.startInVideo;
55
+ }
56
+ openAssets.clear();
57
+ }
52
58
  const current = deduplicateAssets(frames[frame]);
53
59
  const currentIds = new Set(current.map((a) => a.id));
54
60
  for (const [id, openAsset] of openAssets) {
@@ -55,6 +55,7 @@ const path = __importStar(require("node:path"));
55
55
  const node_util_1 = require("node:util");
56
56
  const download_file_1 = require("../assets/download-file");
57
57
  const make_file_executable_1 = require("../compositor/make-file-executable");
58
+ const browser_download_lock_1 = require("./browser-download-lock");
58
59
  const extract_zip_archive_1 = require("./extract-zip-archive");
59
60
  const get_chrome_download_url_1 = require("./get-chrome-download-url");
60
61
  Object.defineProperty(exports, "TESTED_VERSION", { enumerable: true, get: function () { return get_chrome_download_url_1.TESTED_VERSION; } });
@@ -127,8 +128,6 @@ const downloadBrowser = async ({ logLevel, indent, onProgress, version, chromeMo
127
128
  if (installedVersion === expectedVersion) {
128
129
  return (0, exports.getRevisionInfo)(chromeMode);
129
130
  }
130
- // VERSION file missing or mismatched - delete and re-download
131
- fs.rmSync(outputPath, { recursive: true, force: true });
132
131
  }
133
132
  if (!(await existsAsync(downloadsFolder))) {
134
133
  await mkdirAsync(downloadsFolder, {
@@ -142,60 +141,74 @@ const downloadBrowser = async ({ logLevel, indent, onProgress, version, chromeMo
142
141
  'Chrome Headless Shell is not available for Windows for arm64 architecture.',
143
142
  ].join('\n'));
144
143
  }
145
- (0, get_chrome_download_url_1.logDownloadUrl)({ url: downloadURL, logLevel, indent });
144
+ const releaseLock = await (0, browser_download_lock_1.acquireBrowserDownloadLock)(path.join(downloadsFolder, 'download.lock'));
146
145
  try {
147
- await (0, download_file_1.downloadFile)({
148
- url: downloadURL,
149
- to: () => archivePath,
150
- onProgress: (progress) => {
151
- if (progress.totalSize === null || progress.percent === null) {
152
- throw new Error('Expected totalSize and percent to be defined');
153
- }
154
- onProgress({
155
- downloadedBytes: progress.downloaded,
156
- totalSizeInBytes: progress.totalSize,
157
- percent: progress.percent,
158
- alreadyAvailable: false,
159
- });
160
- },
161
- indent,
162
- logLevel,
163
- abortSignal: new AbortController().signal,
164
- });
165
- await (0, extract_zip_archive_1.extractZipArchive)(archivePath, outputPath);
166
- const possibleSubdirs = [
167
- 'chrome-linux',
168
- 'chrome-headless-shell-linux64',
169
- 'chromium-headless-shell-amazon-linux2023-arm64',
170
- 'chromium-headless-shell-amazon-linux2023-x64',
171
- ];
172
- for (const subdir of possibleSubdirs) {
173
- const chromeLinuxFolder = path.join(outputPath, subdir);
174
- const chromePath = path.join(chromeLinuxFolder, 'chrome');
175
- if (fs.existsSync(chromePath)) {
176
- const chromeHeadlessShellPath = path.join(chromeLinuxFolder, 'chrome-headless-shell');
177
- fs.renameSync(chromePath, chromeHeadlessShellPath);
146
+ if (await existsAsync(outputPath)) {
147
+ const installedVersion = (0, exports.readVersionFile)(chromeMode);
148
+ if (installedVersion === expectedVersion) {
149
+ return (0, exports.getRevisionInfo)(chromeMode);
178
150
  }
179
- if (fs.existsSync(chromeLinuxFolder)) {
180
- const targetFolder = path.join(outputPath, 'chrome-headless-shell-' + platform);
181
- if (chromeLinuxFolder !== targetFolder) {
182
- fs.renameSync(chromeLinuxFolder, targetFolder);
151
+ // VERSION file missing or mismatched - delete and re-download
152
+ fs.rmSync(outputPath, { recursive: true, force: true });
153
+ }
154
+ (0, get_chrome_download_url_1.logDownloadUrl)({ url: downloadURL, logLevel, indent });
155
+ try {
156
+ await (0, download_file_1.downloadFile)({
157
+ url: downloadURL,
158
+ to: () => archivePath,
159
+ onProgress: (progress) => {
160
+ if (progress.totalSize === null || progress.percent === null) {
161
+ throw new Error('Expected totalSize and percent to be defined');
162
+ }
163
+ onProgress({
164
+ downloadedBytes: progress.downloaded,
165
+ totalSizeInBytes: progress.totalSize,
166
+ percent: progress.percent,
167
+ alreadyAvailable: false,
168
+ });
169
+ },
170
+ indent,
171
+ logLevel,
172
+ abortSignal: new AbortController().signal,
173
+ });
174
+ await (0, extract_zip_archive_1.extractZipArchive)(archivePath, outputPath);
175
+ const possibleSubdirs = [
176
+ 'chrome-linux',
177
+ 'chrome-headless-shell-linux64',
178
+ 'chromium-headless-shell-amazon-linux2023-arm64',
179
+ 'chromium-headless-shell-amazon-linux2023-x64',
180
+ ];
181
+ for (const subdir of possibleSubdirs) {
182
+ const chromeLinuxFolder = path.join(outputPath, subdir);
183
+ const chromePath = path.join(chromeLinuxFolder, 'chrome');
184
+ if (fs.existsSync(chromePath)) {
185
+ const chromeHeadlessShellPath = path.join(chromeLinuxFolder, 'chrome-headless-shell');
186
+ fs.renameSync(chromePath, chromeHeadlessShellPath);
187
+ }
188
+ if (fs.existsSync(chromeLinuxFolder)) {
189
+ const targetFolder = path.join(outputPath, 'chrome-headless-shell-' + platform);
190
+ if (chromeLinuxFolder !== targetFolder) {
191
+ fs.renameSync(chromeLinuxFolder, targetFolder);
192
+ }
183
193
  }
184
194
  }
185
195
  }
186
- }
187
- catch (err) {
188
- return Promise.reject(err);
196
+ catch (err) {
197
+ return Promise.reject(err);
198
+ }
199
+ finally {
200
+ if (await existsAsync(archivePath)) {
201
+ await unlinkAsync(archivePath);
202
+ }
203
+ }
204
+ writeVersionFile(chromeMode, expectedVersion);
205
+ const revisionInfo = (0, exports.getRevisionInfo)(chromeMode);
206
+ (0, make_file_executable_1.makeFileExecutableIfItIsNot)(revisionInfo.executablePath);
207
+ return revisionInfo;
189
208
  }
190
209
  finally {
191
- if (await existsAsync(archivePath)) {
192
- await unlinkAsync(archivePath);
193
- }
210
+ await releaseLock();
194
211
  }
195
- writeVersionFile(chromeMode, expectedVersion);
196
- const revisionInfo = (0, exports.getRevisionInfo)(chromeMode);
197
- (0, make_file_executable_1.makeFileExecutableIfItIsNot)(revisionInfo.executablePath);
198
- return revisionInfo;
199
212
  };
200
213
  exports.downloadBrowser = downloadBrowser;
201
214
  const getFolderPath = (downloadsFolder, platform) => {
@@ -0,0 +1 @@
1
+ export declare const acquireBrowserDownloadLock: (lockPath: string) => Promise<() => Promise<void>>;
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.acquireBrowserDownloadLock = void 0;
40
+ const node_crypto_1 = require("node:crypto");
41
+ const fs = __importStar(require("node:fs"));
42
+ const node_os_1 = __importDefault(require("node:os"));
43
+ const RETRY_INTERVAL_IN_MS = 100;
44
+ const STALE_LOCK_IN_MS = 30000;
45
+ const HEARTBEAT_INTERVAL_IN_MS = 5000;
46
+ const wait = (timeoutInMilliseconds) => {
47
+ return new Promise((resolve) => {
48
+ setTimeout(resolve, timeoutInMilliseconds);
49
+ });
50
+ };
51
+ const isErrorWithCode = (error, code) => {
52
+ return (error instanceof Error &&
53
+ 'code' in error &&
54
+ error.code === code);
55
+ };
56
+ const readLock = async (lockPath) => {
57
+ try {
58
+ const parsed = JSON.parse(await fs.promises.readFile(lockPath, 'utf8'));
59
+ if (typeof parsed.hostname !== 'string' ||
60
+ typeof parsed.pid !== 'number' ||
61
+ typeof parsed.token !== 'string') {
62
+ return null;
63
+ }
64
+ return parsed;
65
+ }
66
+ catch (_a) {
67
+ return null;
68
+ }
69
+ };
70
+ const isProcessRunning = (pid) => {
71
+ try {
72
+ process.kill(pid, 0);
73
+ return true;
74
+ }
75
+ catch (error) {
76
+ return !isErrorWithCode(error, 'ESRCH');
77
+ }
78
+ };
79
+ const removeStaleLock = async (lockPath) => {
80
+ let stats;
81
+ try {
82
+ stats = await fs.promises.stat(lockPath);
83
+ }
84
+ catch (error) {
85
+ if (isErrorWithCode(error, 'ENOENT')) {
86
+ return;
87
+ }
88
+ throw error;
89
+ }
90
+ const lock = await readLock(lockPath);
91
+ if ((lock === null || lock === void 0 ? void 0 : lock.hostname) === node_os_1.default.hostname()) {
92
+ if (isProcessRunning(lock.pid)) {
93
+ return;
94
+ }
95
+ }
96
+ else if (Date.now() - stats.mtimeMs < STALE_LOCK_IN_MS) {
97
+ return;
98
+ }
99
+ try {
100
+ await fs.promises.unlink(lockPath);
101
+ }
102
+ catch (error) {
103
+ if (!isErrorWithCode(error, 'ENOENT')) {
104
+ throw error;
105
+ }
106
+ }
107
+ };
108
+ const acquireBrowserDownloadLock = async (lockPath) => {
109
+ // Browser archives and extraction directories are shared by every Remotion
110
+ // process in a project, so the whole installation must be cross-process safe.
111
+ for (;;) {
112
+ const token = (0, node_crypto_1.randomUUID)();
113
+ let lockFile;
114
+ try {
115
+ lockFile = await fs.promises.open(lockPath, 'wx');
116
+ }
117
+ catch (error) {
118
+ if (!isErrorWithCode(error, 'EEXIST')) {
119
+ throw error;
120
+ }
121
+ await removeStaleLock(lockPath);
122
+ await wait(RETRY_INTERVAL_IN_MS);
123
+ continue;
124
+ }
125
+ try {
126
+ await lockFile.writeFile(JSON.stringify({
127
+ hostname: node_os_1.default.hostname(),
128
+ pid: process.pid,
129
+ token,
130
+ }));
131
+ }
132
+ catch (error) {
133
+ await lockFile.close();
134
+ await fs.promises.rm(lockPath, { force: true });
135
+ throw error;
136
+ }
137
+ const heartbeat = setInterval(async () => {
138
+ const currentLock = await readLock(lockPath);
139
+ if ((currentLock === null || currentLock === void 0 ? void 0 : currentLock.token) !== token) {
140
+ return;
141
+ }
142
+ const now = new Date();
143
+ try {
144
+ await fs.promises.utimes(lockPath, now, now);
145
+ }
146
+ catch (_a) {
147
+ // The lock may have been cleaned up while the heartbeat was pending.
148
+ }
149
+ }, HEARTBEAT_INTERVAL_IN_MS);
150
+ heartbeat.unref();
151
+ return async () => {
152
+ clearInterval(heartbeat);
153
+ const currentLock = await readLock(lockPath);
154
+ await lockFile.close();
155
+ if ((currentLock === null || currentLock === void 0 ? void 0 : currentLock.token) === token) {
156
+ await fs.promises.rm(lockPath, { force: true });
157
+ }
158
+ };
159
+ }
160
+ };
161
+ exports.acquireBrowserDownloadLock = acquireBrowserDownloadLock;
package/dist/client.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export { AvailableOptions, TypeOfOption } from './options';
2
+ export { customEditorColumnNumberPlaceholder, customEditorLineNumberPlaceholder, customEditorTargetPathPlaceholder, defaultEditorIds, } from './options/default-editor';
3
+ export type { BuiltInEditor, CustomEditor, DefaultEditor, } from './options/default-editor';
2
4
  export { HardwareAccelerationOption } from './options/hardware-acceleration';
3
5
  export { ProResProfile } from './options/prores-profile';
4
6
  export declare const BrowserSafeApis: {
@@ -1278,6 +1280,22 @@ export declare const BrowserSafeApis: {
1278
1280
  setConfig: (value: boolean) => void;
1279
1281
  id: "dark-mode";
1280
1282
  };
1283
+ defaultEditorOption: {
1284
+ name: string;
1285
+ cliFlag: "editor";
1286
+ description: () => import("react/jsx-runtime").JSX.Element;
1287
+ ssrName: null;
1288
+ docLink: string;
1289
+ type: import("./client").DefaultEditor | null;
1290
+ getValue: ({ commandLine }: {
1291
+ commandLine: Record<string, unknown>;
1292
+ }) => {
1293
+ value: import("./client").DefaultEditor | null;
1294
+ source: string;
1295
+ };
1296
+ setConfig(value: import("./client").DefaultEditor | null): void;
1297
+ id: "editor";
1298
+ };
1281
1299
  publicLicenseKeyOption: {
1282
1300
  name: string;
1283
1301
  cliFlag: "public-license-key";
@@ -1364,14 +1382,14 @@ export declare const BrowserSafeApis: {
1364
1382
  description: () => import("react/jsx-runtime").JSX.Element;
1365
1383
  ssrName: "frameRange";
1366
1384
  docLink: string;
1367
- type: import("./frame-range").FrameRange | null;
1385
+ type: import("./frame-range").FrameSelection;
1368
1386
  getValue: ({ commandLine }: {
1369
1387
  commandLine: Record<string, unknown>;
1370
1388
  }) => {
1371
1389
  source: string;
1372
- value: import("./frame-range").FrameRange | null;
1390
+ value: import("./frame-range").FrameSelection;
1373
1391
  };
1374
- setConfig: (value: import("./frame-range").FrameRange | null) => void;
1392
+ setConfig: (value: import("./frame-range").FrameSelection) => void;
1375
1393
  id: "frames";
1376
1394
  };
1377
1395
  forceNewStudioOption: {
@@ -1565,7 +1583,7 @@ export declare const BrowserSafeApis: {
1565
1583
  };
1566
1584
  rspackOption: {
1567
1585
  name: string;
1568
- cliFlag: "experimental-rspack";
1586
+ cliFlag: "rspack";
1569
1587
  description: () => import("react/jsx-runtime").JSX.Element;
1570
1588
  ssrName: null;
1571
1589
  docLink: null;
@@ -1577,7 +1595,7 @@ export declare const BrowserSafeApis: {
1577
1595
  source: string;
1578
1596
  };
1579
1597
  setConfig(value: boolean): void;
1580
- id: "experimental-rspack";
1598
+ id: "rspack";
1581
1599
  };
1582
1600
  outDirOption: {
1583
1601
  name: string;
@@ -1617,6 +1635,25 @@ export declare const BrowserSafeApis: {
1617
1635
  type: string | null;
1618
1636
  id: "package-manager";
1619
1637
  };
1638
+ skipSkillsOption: {
1639
+ name: string;
1640
+ cliFlag: "skip-skills";
1641
+ description: () => import("react/jsx-runtime").JSX.Element;
1642
+ ssrName: null;
1643
+ docLink: string;
1644
+ getValue: ({ commandLine }: {
1645
+ commandLine: Record<string, unknown>;
1646
+ }) => {
1647
+ source: string;
1648
+ value: true;
1649
+ } | {
1650
+ source: string;
1651
+ value: false;
1652
+ };
1653
+ setConfig: () => never;
1654
+ type: boolean;
1655
+ id: "skip-skills";
1656
+ };
1620
1657
  sampleRateOption: {
1621
1658
  name: string;
1622
1659
  cliFlag: "sample-rate";
package/dist/client.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BrowserSafeApis = void 0;
3
+ exports.BrowserSafeApis = exports.defaultEditorIds = exports.customEditorTargetPathPlaceholder = exports.customEditorLineNumberPlaceholder = exports.customEditorColumnNumberPlaceholder = void 0;
4
4
  const no_react_1 = require("remotion/no-react");
5
5
  const TimeoutSettings_1 = require("./browser/TimeoutSettings");
6
6
  const codec_1 = require("./codec");
@@ -22,6 +22,11 @@ const video_codec_1 = require("./options/video-codec");
22
22
  const x264_preset_1 = require("./options/x264-preset");
23
23
  const pixel_format_1 = require("./pixel-format");
24
24
  const validate_output_filename_1 = require("./validate-output-filename");
25
+ const default_editor_1 = require("./options/default-editor");
26
+ Object.defineProperty(exports, "customEditorColumnNumberPlaceholder", { enumerable: true, get: function () { return default_editor_1.customEditorColumnNumberPlaceholder; } });
27
+ Object.defineProperty(exports, "customEditorLineNumberPlaceholder", { enumerable: true, get: function () { return default_editor_1.customEditorLineNumberPlaceholder; } });
28
+ Object.defineProperty(exports, "customEditorTargetPathPlaceholder", { enumerable: true, get: function () { return default_editor_1.customEditorTargetPathPlaceholder; } });
29
+ Object.defineProperty(exports, "defaultEditorIds", { enumerable: true, get: function () { return default_editor_1.defaultEditorIds; } });
25
30
  exports.BrowserSafeApis = {
26
31
  getFileExtensionFromCodec: get_extension_from_codec_1.getFileExtensionFromCodec,
27
32
  validCodecs: codec_1.validCodecs,
@@ -1,5 +1,5 @@
1
1
  import type { Codec } from './codec';
2
- import type { FrameRange } from './frame-range';
2
+ import type { SingleFrameRange } from './frame-range';
3
3
  import type { LogLevel } from './log-level';
4
4
  import type { CancelSignal } from './make-cancel-signal';
5
5
  import type { AudioCodec } from './options/audio-codec';
@@ -27,7 +27,7 @@ type OptionalCombineChunksOptions = {
27
27
  audioCodec: AudioCodec | null;
28
28
  cancelSignal: CancelSignal | undefined;
29
29
  metadata: Record<string, string> | null;
30
- frameRange: FrameRange | null;
30
+ frameRange: SingleFrameRange | null;
31
31
  everyNthFrame: number;
32
32
  sampleRate: number;
33
33
  };
@@ -45,8 +45,8 @@ const internalCombineChunks = async ({ outputLocation: output, onProgress, codec
45
45
  });
46
46
  const shouldCreateAudio = resolvedAudioCodec !== null && audioFiles.length > 0;
47
47
  const seamlessVideo = (0, can_concat_seamlessly_1.canConcatVideoSeamlessly)(codec);
48
- const seamlessAudio = (0, can_concat_seamlessly_1.canConcatAudioSeamlessly)(resolvedAudioCodec, framesPerChunk);
49
48
  const realFrameRange = (0, get_frame_to_render_1.getRealFrameRange)(compositionDurationInFrames, frameRange);
49
+ const seamlessAudio = (0, can_concat_seamlessly_1.canConcatAudioSeamlessly)(resolvedAudioCodec, framesPerChunk);
50
50
  const numberOfFrames = (0, get_duration_from_frame_range_1.getFramesToRender)(realFrameRange, everyNthFrame).length;
51
51
  const videoOutput = shouldCreateVideo
52
52
  ? (0, node_path_1.join)(filelistDir, `video.${(0, get_extension_from_codec_1.getFileExtensionFromCodec)(codec, resolvedAudioCodec)}`)
@@ -25,7 +25,7 @@ const createAudio = async ({ assets, onDownload, fps, logLevel, onProgress, down
25
25
  binariesDirectory,
26
26
  });
27
27
  (0, download_and_map_assets_to_file_1.markAllAssetsAsDownloaded)(downloadMap);
28
- const assetPositions = (0, calculate_asset_positions_1.calculateAssetPositions)(fileUrlAssets);
28
+ const assetPositions = (0, calculate_asset_positions_1.calculateAssetPositions)(fileUrlAssets, assets.map((asset) => asset.frame));
29
29
  logger_1.Log.verbose({ indent, logLevel, tag: 'audio' }, 'asset positions', JSON.stringify(assetPositions));
30
30
  const preprocessProgress = new Array(assetPositions.length).fill(0);
31
31
  let mergeProgress = 0;