polotno-node 2.9.39 → 2.10.0

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 (2) hide show
  1. package/package.json +1 -1
  2. package/video-parallel.js +33 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polotno-node",
3
- "version": "2.9.39",
3
+ "version": "2.10.0",
4
4
  "description": "Polotno workflow from NodeJS",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/video-parallel.js CHANGED
@@ -116,6 +116,20 @@ module.exports.jsonToVideo = async function jsonToVideo(
116
116
  })
117
117
  );
118
118
 
119
+ const audios = [];
120
+ // download all audio tracks
121
+ await Promise.all(
122
+ (json.audios || []).map(async (audio) => {
123
+ const filename = Math.random().toString(36).substring(7);
124
+ const destination = path.join(tempFolder.name, filename);
125
+ await downloadVideo(audio.src, destination);
126
+ audios.push({
127
+ ...audio,
128
+ file: destination,
129
+ });
130
+ })
131
+ );
132
+
119
133
  const duration = json.pages.reduce((acc, page) => {
120
134
  return acc + (page.duration ?? 5000);
121
135
  }, 0);
@@ -315,21 +329,31 @@ module.exports.jsonToVideo = async function jsonToVideo(
315
329
  // Map the video stream from the image sequence
316
330
  ffmpegCmd.outputOptions(['-map 0:v']);
317
331
 
318
- // Prepare audio filter complex only if there are audio inputs
319
- if (audioInputs.length > 0) {
320
- const audioFilters = audioInputs.map(
321
- (input, i) =>
322
- `[${input.index}:a]adelay=${input.delay}|${input.delay},volume=${input.volume}[a${i}]`
323
- );
324
- const audioMerge = audioInputs.map((_, i) => `[a${i}]`).join('');
332
+ // Prepare audio filter complex for both video and pure audio inputs
333
+ const allAudioInputs = [...audioInputs, ...audios];
334
+ if (allAudioInputs.length > 0) {
335
+ const audioFilters = allAudioInputs.map((input, i) => {
336
+ const inputIndex = audioInputs.includes(input)
337
+ ? input.index
338
+ : audioInputs.length + i + 1;
339
+ return `[${inputIndex}:a]adelay=${input.delay}|${input.delay},volume=${input.volume},apad[a${i}]`;
340
+ });
341
+ const audioMerge = allAudioInputs.map((_, i) => `[a${i}]`).join('');
325
342
  const filterComplex = `${audioFilters.join(
326
343
  ';'
327
344
  )};${audioMerge}amix=inputs=${
328
- audioInputs.length
329
- }:duration=longest[aout]`;
345
+ allAudioInputs.length
346
+ }:dropout_transition=0,aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,apad,atrim=0:${
347
+ duration / 1000
348
+ }[aout]`;
330
349
 
331
350
  ffmpegCmd.complexFilter(filterComplex);
332
351
  ffmpegCmd.outputOptions(['-map [aout]']);
352
+
353
+ // Add pure audio inputs
354
+ audios.forEach((audio) => {
355
+ ffmpegCmd.input(audio.file);
356
+ });
333
357
  }
334
358
 
335
359
  ffmpegCmd