n8n-nodes-ffmpeg-wasm 1.2.4 → 1.2.6

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.
@@ -4,32 +4,16 @@ exports.FFmpegWasmApi = void 0;
4
4
  class FFmpegWasmApi {
5
5
  constructor() {
6
6
  this.name = "ffmpegWasmApi";
7
- this.displayName = "FFmpeg.wasm API";
8
- this.documentationUrl = "https://ffmpegwasm.netlify.app/docs/overview";
7
+ this.displayName = "FFmpeg.wasm Configuration";
8
+ this.documentationUrl = "https://github.com/ffmpegwasm/ffmpeg.wasm";
9
9
  this.properties = [
10
10
  {
11
- displayName: "Core URL",
12
- name: "coreURL",
11
+ displayName: "Core Path",
12
+ name: "corePath",
13
13
  type: "string",
14
14
  default: "",
15
- placeholder: "https://unpkg.com/@ffmpeg/core@0.12.6/dist/umd/ffmpeg-core.js",
16
- description: "Custom URL for FFmpeg core (optional - leave empty to use default)",
17
- },
18
- {
19
- displayName: "Wasm URL",
20
- name: "wasmURL",
21
- type: "string",
22
- default: "",
23
- placeholder: "https://unpkg.com/@ffmpeg/core@0.12.6/dist/umd/ffmpeg-core.wasm",
24
- description: "Custom URL for FFmpeg WASM binary (optional - leave empty to use default)",
25
- },
26
- {
27
- displayName: "Worker URL",
28
- name: "workerURL",
29
- type: "string",
30
- default: "",
31
- placeholder: "https://unpkg.com/@ffmpeg/core@0.12.6/dist/umd/ffmpeg-core.worker.js",
32
- description: "Custom URL for FFmpeg worker (optional - leave empty to use default)",
15
+ placeholder: "https://unpkg.com/@ffmpeg/core@0.11.0/dist/ffmpeg-core.js",
16
+ description: "Custom URL or local path to ffmpeg-core.js (optional - leave empty to use CDN default)",
33
17
  },
34
18
  ];
35
19
  }
@@ -960,29 +960,26 @@ class FFmpegWasm {
960
960
  async execute() {
961
961
  const items = this.getInputData();
962
962
  const returnData = [];
963
- const ffmpeg = new ffmpeg_1.FFmpeg();
963
+ let corePath;
964
964
  try {
965
- const loadOptions = {};
966
- try {
967
- const credentials = await this.getCredentials("ffmpegWasmApi");
968
- if (credentials.coreURL)
969
- loadOptions.coreURL = credentials.coreURL;
970
- if (credentials.wasmURL)
971
- loadOptions.wasmURL = credentials.wasmURL;
972
- if (credentials.workerURL)
973
- loadOptions.workerURL = credentials.workerURL;
965
+ const credentials = await this.getCredentials("ffmpegWasmApi");
966
+ if (credentials.corePath) {
967
+ corePath = credentials.corePath;
974
968
  }
975
- catch {
976
- }
977
- await ffmpeg.load(Object.keys(loadOptions).length > 0 ? loadOptions : undefined);
978
- let lastLogOutput = "";
979
- const firstOpts = this.getNodeParameter("additionalOptions", 0, {});
980
- ffmpeg.on("log", ({ message }) => {
969
+ }
970
+ catch {
971
+ }
972
+ let lastLogOutput = "";
973
+ const firstOpts = this.getNodeParameter("additionalOptions", 0, {});
974
+ const ffmpeg = (0, ffmpeg_1.createFFmpeg)({
975
+ log: firstOpts.enableLogging || false,
976
+ logger: ({ message }) => {
981
977
  lastLogOutput += message + "\n";
982
- if (firstOpts.enableLogging) {
983
- console.log(`FFmpeg: ${message}`);
984
- }
985
- });
978
+ },
979
+ ...(corePath ? { corePath } : {}),
980
+ });
981
+ try {
982
+ await ffmpeg.load();
986
983
  for (let i = 0; i < items.length; i++) {
987
984
  try {
988
985
  const binaryPropertyName = this.getNodeParameter("binaryPropertyName", i);
@@ -996,12 +993,16 @@ class FFmpegWasm {
996
993
  const inputFilename = `input_${i}_${Date.now()}${inputExt}`;
997
994
  const outputFilename = `output_${i}_${Date.now()}`;
998
995
  const inputData = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
999
- await ffmpeg.writeFile(inputFilename, inputData);
996
+ ffmpeg.FS("writeFile", inputFilename, new Uint8Array(inputData));
1000
997
  let ffmpegCommand = [];
1001
998
  let outputExt = "";
1002
999
  if (operation === "metadata") {
1003
1000
  lastLogOutput = "";
1004
- await ffmpeg.exec(["-i", inputFilename, "-hide_banner"]);
1001
+ try {
1002
+ await ffmpeg.run("-i", inputFilename, "-hide_banner");
1003
+ }
1004
+ catch {
1005
+ }
1005
1006
  const metadata = (0, helpers_1.parseMetadataFromLogs)(lastLogOutput);
1006
1007
  returnData.push({
1007
1008
  json: {
@@ -1010,7 +1011,7 @@ class FFmpegWasm {
1010
1011
  },
1011
1012
  });
1012
1013
  try {
1013
- await ffmpeg.deleteFile(inputFilename);
1014
+ ffmpeg.FS("unlink", inputFilename);
1014
1015
  }
1015
1016
  catch { }
1016
1017
  continue;
@@ -1133,14 +1134,14 @@ class FFmpegWasm {
1133
1134
  : ".mp4";
1134
1135
  const videoData = await this.helpers.getBinaryDataBuffer(i, propName);
1135
1136
  const inputName = `input_${i}_${j}_${Date.now()}${ext}`;
1136
- await ffmpeg.writeFile(inputName, videoData);
1137
+ ffmpeg.FS("writeFile", inputName, new Uint8Array(videoData));
1137
1138
  inputFiles.push(inputName);
1138
1139
  }
1139
1140
  const concatList = inputFiles
1140
1141
  .map((f) => `file '${f}'`)
1141
1142
  .join("\n");
1142
1143
  const listFilename = `list_${i}_${Date.now()}.txt`;
1143
- await ffmpeg.writeFile(listFilename, new TextEncoder().encode(concatList));
1144
+ ffmpeg.FS("writeFile", listFilename, new TextEncoder().encode(concatList));
1144
1145
  outputExt = (0, helpers_1.normalizeExtension)(mergeOutputFormat);
1145
1146
  const outputName = `${outputFilename}${outputExt}`;
1146
1147
  if (addTransition) {
@@ -1353,7 +1354,7 @@ class FFmpegWasm {
1353
1354
  : ".wav";
1354
1355
  const audioData = await this.helpers.getBinaryDataBuffer(i, propName);
1355
1356
  const inputName = `audio_input_${i}_${j}_${Date.now()}${ext}`;
1356
- await ffmpeg.writeFile(inputName, audioData);
1357
+ ffmpeg.FS("writeFile", inputName, new Uint8Array(audioData));
1357
1358
  inputFiles.push(inputName);
1358
1359
  }
1359
1360
  outputExt = (0, helpers_1.normalizeExtension)(audioMixOutputFormat);
@@ -1448,7 +1449,7 @@ class FFmpegWasm {
1448
1449
  : ".png";
1449
1450
  const overlayData = await this.helpers.getBinaryDataBuffer(i, overlayBinaryProperty);
1450
1451
  const overlayFilename = `overlay_${i}_${Date.now()}${overlayExt}`;
1451
- await ffmpeg.writeFile(overlayFilename, overlayData);
1452
+ ffmpeg.FS("writeFile", overlayFilename, new Uint8Array(overlayData));
1452
1453
  outputExt = (0, helpers_1.normalizeExtension)(overlayOutputFormat);
1453
1454
  const outputName = `${outputFilename}${outputExt}`;
1454
1455
  let videoFilter = "";
@@ -1520,7 +1521,7 @@ class FFmpegWasm {
1520
1521
  const subtitleOutputFormat = this.getNodeParameter("subtitleOutputFormat", i);
1521
1522
  const subtitleData = await this.helpers.getBinaryDataBuffer(i, subtitleBinaryProperty);
1522
1523
  const subtitleFilename = `subtitle_${i}_${Date.now()}.${subtitleFormat}`;
1523
- await ffmpeg.writeFile(subtitleFilename, subtitleData);
1524
+ ffmpeg.FS("writeFile", subtitleFilename, new Uint8Array(subtitleData));
1524
1525
  outputExt = (0, helpers_1.normalizeExtension)(subtitleOutputFormat);
1525
1526
  const outputName = `${outputFilename}${outputExt}`;
1526
1527
  const assColor = (0, helpers_1.colorToAssFormat)(subtitleFontColor);
@@ -1639,7 +1640,7 @@ class FFmpegWasm {
1639
1640
  const seqTimeoutMs = (additionalOptions.timeout || 300) * 1000;
1640
1641
  lastLogOutput = "";
1641
1642
  await Promise.race([
1642
- ffmpeg.exec(ffmpegCommand),
1643
+ ffmpeg.run(...ffmpegCommand),
1643
1644
  new Promise((_, reject) => setTimeout(() => reject(new Error(`FFmpeg timed out after ${additionalOptions.timeout || 300}s`)), seqTimeoutMs)),
1644
1645
  ]);
1645
1646
  const mimeType = (0, helpers_1.getMimeTypeFromExtension)(sequenceOutputFormat);
@@ -1647,7 +1648,7 @@ class FFmpegWasm {
1647
1648
  while (true) {
1648
1649
  const frameName = `frame_${String(frameIndex).padStart(4, "0")}.${sequenceOutputFormat}`;
1649
1650
  try {
1650
- const frameData = (await ffmpeg.readFile(frameName));
1651
+ const frameData = ffmpeg.FS("readFile", frameName);
1651
1652
  returnData.push({
1652
1653
  json: {
1653
1654
  ...items[i].json,
@@ -1667,7 +1668,10 @@ class FFmpegWasm {
1667
1668
  },
1668
1669
  },
1669
1670
  });
1670
- await ffmpeg.deleteFile(frameName);
1671
+ try {
1672
+ ffmpeg.FS("unlink", frameName);
1673
+ }
1674
+ catch { }
1671
1675
  frameIndex++;
1672
1676
  }
1673
1677
  catch {
@@ -1675,7 +1679,7 @@ class FFmpegWasm {
1675
1679
  }
1676
1680
  }
1677
1681
  try {
1678
- await ffmpeg.deleteFile(inputFilename);
1682
+ ffmpeg.FS("unlink", inputFilename);
1679
1683
  }
1680
1684
  catch { }
1681
1685
  continue;
@@ -1733,11 +1737,11 @@ class FFmpegWasm {
1733
1737
  outputExt = (0, helpers_1.normalizeExtension)(compressOutputFormat);
1734
1738
  const outputName = `${outputFilename}${outputExt}`;
1735
1739
  lastLogOutput = "";
1736
- await ffmpeg.exec([
1737
- "-i",
1738
- inputFilename,
1739
- "-hide_banner",
1740
- ]);
1740
+ try {
1741
+ await ffmpeg.run("-i", inputFilename, "-hide_banner");
1742
+ }
1743
+ catch {
1744
+ }
1741
1745
  const meta = (0, helpers_1.parseMetadataFromLogs)(lastLogOutput);
1742
1746
  const durationSec = meta.durationSeconds || 60;
1743
1747
  const audioBitrateKbps = parseInt(compressAudioBitrate) || 128;
@@ -1771,11 +1775,11 @@ class FFmpegWasm {
1771
1775
  const timeoutMs = (additionalOptions.timeout || 300) * 1000;
1772
1776
  lastLogOutput = "";
1773
1777
  await Promise.race([
1774
- ffmpeg.exec(ffmpegCommand),
1778
+ ffmpeg.run(...ffmpegCommand),
1775
1779
  new Promise((_, reject) => setTimeout(() => reject(new Error(`FFmpeg timed out after ${additionalOptions.timeout || 300}s`)), timeoutMs)),
1776
1780
  ]);
1777
1781
  const outputName = `${outputFilename}${outputExt}`;
1778
- const outputData = (await ffmpeg.readFile(outputName));
1782
+ const outputData = ffmpeg.FS("readFile", outputName);
1779
1783
  const outputMimeType = (0, helpers_1.getMimeTypeFromExtension)(outputExt.replace(".", ""));
1780
1784
  const outputItem = {
1781
1785
  json: {
@@ -1797,8 +1801,8 @@ class FFmpegWasm {
1797
1801
  };
1798
1802
  returnData.push(outputItem);
1799
1803
  try {
1800
- await ffmpeg.deleteFile(inputFilename);
1801
- await ffmpeg.deleteFile(outputName);
1804
+ ffmpeg.FS("unlink", inputFilename);
1805
+ ffmpeg.FS("unlink", outputName);
1802
1806
  }
1803
1807
  catch { }
1804
1808
  }
@@ -1809,18 +1813,20 @@ class FFmpegWasm {
1809
1813
  ...items[i].json,
1810
1814
  error: error instanceof Error
1811
1815
  ? error.message
1812
- : "Unknown error",
1816
+ : String(error),
1813
1817
  },
1814
1818
  });
1815
1819
  }
1816
1820
  else {
1817
- throw error;
1821
+ if (error instanceof Error)
1822
+ throw error;
1823
+ throw new Error(String(error));
1818
1824
  }
1819
1825
  }
1820
1826
  }
1821
1827
  }
1822
1828
  finally {
1823
- ffmpeg.terminate();
1829
+ ffmpeg.exit();
1824
1830
  }
1825
1831
  return [returnData];
1826
1832
  }
package/logo.png CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-ffmpeg-wasm",
3
- "version": "1.2.4",
3
+ "version": "1.2.6",
4
4
  "description": "n8n community node for FFmpeg using ffmpeg.wasm - process audio and video files directly in your workflows",
5
5
  "keywords": [
6
6
  "n8n",
@@ -68,7 +68,7 @@
68
68
  "typescript": "^5.3.0"
69
69
  },
70
70
  "dependencies": {
71
- "@ffmpeg/ffmpeg": "^0.12.10"
71
+ "@ffmpeg/ffmpeg": "^0.11.6"
72
72
  },
73
73
  "peerDependencies": {
74
74
  "n8n-workflow": ">=1.0.0"