@xyo-network/image-thumbnail-plugin 2.74.5 → 2.75.2

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 (195) hide show
  1. package/dist/docs.json +1299 -1299
  2. package/dist/node/Diviner/Config.d.cts.map +1 -0
  3. package/dist/node/Diviner/Config.d.mts.map +1 -0
  4. package/dist/node/Diviner/Config.d.ts +11 -0
  5. package/dist/node/Diviner/Config.d.ts.map +1 -0
  6. package/dist/node/Diviner/Config.js +32 -0
  7. package/dist/node/Diviner/Config.js.map +1 -0
  8. package/dist/node/Diviner/Config.mjs +7 -0
  9. package/dist/node/Diviner/Config.mjs.map +1 -0
  10. package/dist/node/Diviner/Diviner.d.cts.map +1 -0
  11. package/dist/node/Diviner/Diviner.d.mts.map +1 -0
  12. package/dist/node/Diviner/Diviner.d.ts +30 -0
  13. package/dist/node/Diviner/Diviner.d.ts.map +1 -0
  14. package/dist/node/Diviner/Diviner.js +207 -0
  15. package/dist/node/Diviner/Diviner.js.map +1 -0
  16. package/dist/node/Diviner/Diviner.mjs +182 -0
  17. package/dist/node/Diviner/Diviner.mjs.map +1 -0
  18. package/dist/node/Diviner/Params.d.cts.map +1 -0
  19. package/dist/node/Diviner/Params.d.mts.map +1 -0
  20. package/dist/node/Diviner/Params.d.ts +5 -0
  21. package/dist/node/Diviner/Params.d.ts.map +1 -0
  22. package/dist/node/Diviner/Params.js +19 -0
  23. package/dist/node/Diviner/Params.js.map +1 -0
  24. package/dist/node/Diviner/Params.mjs +1 -0
  25. package/dist/node/Diviner/Params.mjs.map +1 -0
  26. package/dist/node/Diviner/index.d.cts.map +1 -0
  27. package/dist/node/Diviner/index.d.mts.map +1 -0
  28. package/dist/node/Diviner/index.d.ts +4 -0
  29. package/dist/node/Diviner/index.d.ts.map +1 -0
  30. package/dist/node/Diviner/index.js +209 -0
  31. package/dist/node/Diviner/index.js.map +1 -0
  32. package/dist/node/Diviner/index.mjs +181 -0
  33. package/dist/node/Diviner/index.mjs.map +1 -0
  34. package/dist/node/Plugin.d.cts.map +1 -0
  35. package/dist/node/Plugin.d.mts.map +1 -0
  36. package/dist/node/Plugin.d.ts +116 -0
  37. package/dist/node/Plugin.d.ts.map +1 -0
  38. package/dist/node/Plugin.js +556 -0
  39. package/dist/{index.mjs.map → node/Plugin.js.map} +1 -1
  40. package/dist/node/Plugin.mjs +521 -0
  41. package/dist/node/Plugin.mjs.map +1 -0
  42. package/dist/node/Witness/Config.d.cts.map +1 -0
  43. package/dist/node/Witness/Config.d.mts.map +1 -0
  44. package/dist/node/Witness/Config.d.ts +16 -0
  45. package/dist/node/Witness/Config.d.ts.map +1 -0
  46. package/dist/node/Witness/Config.js +32 -0
  47. package/dist/node/Witness/Config.js.map +1 -0
  48. package/dist/node/Witness/Config.mjs +7 -0
  49. package/dist/node/Witness/Config.mjs.map +1 -0
  50. package/dist/node/Witness/Params.d.cts.map +1 -0
  51. package/dist/node/Witness/Params.d.mts.map +1 -0
  52. package/dist/node/Witness/Params.d.ts +7 -0
  53. package/dist/node/Witness/Params.d.ts.map +1 -0
  54. package/dist/node/Witness/Params.js +19 -0
  55. package/dist/node/Witness/Params.js.map +1 -0
  56. package/dist/node/Witness/Params.mjs +1 -0
  57. package/dist/node/Witness/Params.mjs.map +1 -0
  58. package/dist/node/Witness/Witness.d.cts.map +1 -0
  59. package/dist/node/Witness/Witness.d.mts.map +1 -0
  60. package/dist/node/Witness/Witness.d.ts +66 -0
  61. package/dist/node/Witness/Witness.d.ts.map +1 -0
  62. package/dist/node/Witness/Witness.js +359 -0
  63. package/dist/node/Witness/Witness.js.map +1 -0
  64. package/dist/node/Witness/Witness.mjs +324 -0
  65. package/dist/node/Witness/Witness.mjs.map +1 -0
  66. package/dist/node/Witness/ffmpeg/fluent/getVideoFrameAsImageFluent.d.cts.map +1 -0
  67. package/dist/node/Witness/ffmpeg/fluent/getVideoFrameAsImageFluent.d.mts.map +1 -0
  68. package/dist/node/Witness/ffmpeg/fluent/getVideoFrameAsImageFluent.d.ts +8 -0
  69. package/dist/node/Witness/ffmpeg/fluent/getVideoFrameAsImageFluent.d.ts.map +1 -0
  70. package/dist/node/Witness/ffmpeg/fluent/getVideoFrameAsImageFluent.js +77 -0
  71. package/dist/node/Witness/ffmpeg/fluent/getVideoFrameAsImageFluent.js.map +1 -0
  72. package/dist/node/Witness/ffmpeg/fluent/getVideoFrameAsImageFluent.mjs +42 -0
  73. package/dist/node/Witness/ffmpeg/fluent/getVideoFrameAsImageFluent.mjs.map +1 -0
  74. package/dist/node/Witness/ffmpeg/fluent/index.d.cts.map +1 -0
  75. package/dist/node/Witness/ffmpeg/fluent/index.d.mts.map +1 -0
  76. package/dist/node/Witness/ffmpeg/fluent/index.d.ts +2 -0
  77. package/dist/node/Witness/ffmpeg/fluent/index.d.ts.map +1 -0
  78. package/dist/node/Witness/ffmpeg/fluent/index.js +79 -0
  79. package/dist/node/Witness/ffmpeg/fluent/index.js.map +1 -0
  80. package/dist/node/Witness/ffmpeg/fluent/index.mjs +42 -0
  81. package/dist/node/Witness/ffmpeg/fluent/index.mjs.map +1 -0
  82. package/dist/node/Witness/ffmpeg/index.d.cts.map +1 -0
  83. package/dist/node/Witness/ffmpeg/index.d.mts.map +1 -0
  84. package/dist/node/Witness/ffmpeg/index.d.ts +3 -0
  85. package/dist/node/Witness/ffmpeg/index.d.ts.map +1 -0
  86. package/dist/node/Witness/ffmpeg/index.js +109 -0
  87. package/dist/node/Witness/ffmpeg/index.js.map +1 -0
  88. package/dist/node/Witness/ffmpeg/index.mjs +70 -0
  89. package/dist/node/Witness/ffmpeg/index.mjs.map +1 -0
  90. package/dist/node/Witness/ffmpeg/spawn/executeFfmpeg.d.cts.map +1 -0
  91. package/dist/node/Witness/ffmpeg/spawn/executeFfmpeg.d.mts.map +1 -0
  92. package/dist/node/Witness/ffmpeg/spawn/executeFfmpeg.d.ts +9 -0
  93. package/dist/node/Witness/ffmpeg/spawn/executeFfmpeg.d.ts.map +1 -0
  94. package/dist/node/Witness/ffmpeg/spawn/executeFfmpeg.js +48 -0
  95. package/dist/node/Witness/ffmpeg/spawn/executeFfmpeg.js.map +1 -0
  96. package/dist/node/Witness/ffmpeg/spawn/executeFfmpeg.mjs +23 -0
  97. package/dist/node/Witness/ffmpeg/spawn/executeFfmpeg.mjs.map +1 -0
  98. package/dist/node/Witness/ffmpeg/spawn/getVideoFrameAsImage.d.cts.map +1 -0
  99. package/dist/node/Witness/ffmpeg/spawn/getVideoFrameAsImage.d.mts.map +1 -0
  100. package/dist/node/Witness/ffmpeg/spawn/getVideoFrameAsImage.d.ts +8 -0
  101. package/dist/node/Witness/ffmpeg/spawn/getVideoFrameAsImage.d.ts.map +1 -0
  102. package/dist/node/Witness/ffmpeg/spawn/getVideoFrameAsImage.js +56 -0
  103. package/dist/node/Witness/ffmpeg/spawn/getVideoFrameAsImage.js.map +1 -0
  104. package/dist/node/Witness/ffmpeg/spawn/getVideoFrameAsImage.mjs +29 -0
  105. package/dist/node/Witness/ffmpeg/spawn/getVideoFrameAsImage.mjs.map +1 -0
  106. package/dist/node/Witness/ffmpeg/spawn/index.d.cts.map +1 -0
  107. package/dist/node/Witness/ffmpeg/spawn/index.d.mts.map +1 -0
  108. package/dist/node/Witness/ffmpeg/spawn/index.d.ts +3 -0
  109. package/dist/node/Witness/ffmpeg/spawn/index.d.ts.map +1 -0
  110. package/dist/node/Witness/ffmpeg/spawn/index.js +58 -0
  111. package/dist/node/Witness/ffmpeg/spawn/index.js.map +1 -0
  112. package/dist/node/Witness/ffmpeg/spawn/index.mjs +30 -0
  113. package/dist/node/Witness/ffmpeg/spawn/index.mjs.map +1 -0
  114. package/dist/node/Witness/index.d.cts.map +1 -0
  115. package/dist/node/Witness/index.d.mts.map +1 -0
  116. package/dist/node/Witness/index.d.ts +4 -0
  117. package/dist/node/Witness/index.d.ts.map +1 -0
  118. package/dist/node/Witness/index.js +363 -0
  119. package/dist/node/Witness/index.js.map +1 -0
  120. package/dist/node/Witness/index.mjs +325 -0
  121. package/dist/node/Witness/index.mjs.map +1 -0
  122. package/dist/node/index.d.cts.map +1 -0
  123. package/dist/node/index.d.mts.map +1 -0
  124. package/dist/node/index.d.ts +6 -0
  125. package/dist/node/index.d.ts.map +1 -0
  126. package/dist/{index.js → node/index.js} +15 -10
  127. package/dist/node/index.js.map +1 -0
  128. package/dist/{index.mjs → node/index.mjs} +15 -10
  129. package/dist/node/index.mjs.map +1 -0
  130. package/package.json +39 -38
  131. package/dist/Diviner/Config.d.mts.map +0 -1
  132. package/dist/Diviner/Config.d.ts.map +0 -1
  133. package/dist/Diviner/Diviner.d.mts.map +0 -1
  134. package/dist/Diviner/Diviner.d.ts.map +0 -1
  135. package/dist/Diviner/Params.d.mts.map +0 -1
  136. package/dist/Diviner/Params.d.ts.map +0 -1
  137. package/dist/Diviner/index.d.mts.map +0 -1
  138. package/dist/Diviner/index.d.ts.map +0 -1
  139. package/dist/Plugin.d.mts.map +0 -1
  140. package/dist/Plugin.d.ts.map +0 -1
  141. package/dist/Witness/Config.d.mts.map +0 -1
  142. package/dist/Witness/Config.d.ts.map +0 -1
  143. package/dist/Witness/Params.d.mts.map +0 -1
  144. package/dist/Witness/Params.d.ts.map +0 -1
  145. package/dist/Witness/Witness.d.mts.map +0 -1
  146. package/dist/Witness/Witness.d.ts.map +0 -1
  147. package/dist/Witness/ffmpeg/fluent/getVideoFrameAsImageFluent.d.mts.map +0 -1
  148. package/dist/Witness/ffmpeg/fluent/getVideoFrameAsImageFluent.d.ts.map +0 -1
  149. package/dist/Witness/ffmpeg/fluent/index.d.mts.map +0 -1
  150. package/dist/Witness/ffmpeg/fluent/index.d.ts.map +0 -1
  151. package/dist/Witness/ffmpeg/index.d.mts.map +0 -1
  152. package/dist/Witness/ffmpeg/index.d.ts.map +0 -1
  153. package/dist/Witness/ffmpeg/spawn/executeFfmpeg.d.mts.map +0 -1
  154. package/dist/Witness/ffmpeg/spawn/executeFfmpeg.d.ts.map +0 -1
  155. package/dist/Witness/ffmpeg/spawn/getVideoFrameAsImage.d.mts.map +0 -1
  156. package/dist/Witness/ffmpeg/spawn/getVideoFrameAsImage.d.ts.map +0 -1
  157. package/dist/Witness/ffmpeg/spawn/index.d.mts.map +0 -1
  158. package/dist/Witness/ffmpeg/spawn/index.d.ts.map +0 -1
  159. package/dist/Witness/index.d.mts.map +0 -1
  160. package/dist/Witness/index.d.ts.map +0 -1
  161. package/dist/index.d.mts.map +0 -1
  162. package/dist/index.d.ts.map +0 -1
  163. package/dist/index.js.map +0 -1
  164. /package/dist/{Diviner/Config.d.mts → node/Diviner/Config.d.cts} +0 -0
  165. /package/dist/{Diviner/Config.d.ts → node/Diviner/Config.d.mts} +0 -0
  166. /package/dist/{Diviner/Diviner.d.mts → node/Diviner/Diviner.d.cts} +0 -0
  167. /package/dist/{Diviner/Diviner.d.ts → node/Diviner/Diviner.d.mts} +0 -0
  168. /package/dist/{Diviner/Params.d.mts → node/Diviner/Params.d.cts} +0 -0
  169. /package/dist/{Diviner/Params.d.ts → node/Diviner/Params.d.mts} +0 -0
  170. /package/dist/{Diviner/index.d.mts → node/Diviner/index.d.cts} +0 -0
  171. /package/dist/{Diviner/index.d.ts → node/Diviner/index.d.mts} +0 -0
  172. /package/dist/{Plugin.d.mts → node/Plugin.d.cts} +0 -0
  173. /package/dist/{Plugin.d.ts → node/Plugin.d.mts} +0 -0
  174. /package/dist/{Witness/Config.d.mts → node/Witness/Config.d.cts} +0 -0
  175. /package/dist/{Witness/Config.d.ts → node/Witness/Config.d.mts} +0 -0
  176. /package/dist/{Witness/Params.d.mts → node/Witness/Params.d.cts} +0 -0
  177. /package/dist/{Witness/Params.d.ts → node/Witness/Params.d.mts} +0 -0
  178. /package/dist/{Witness/Witness.d.mts → node/Witness/Witness.d.cts} +0 -0
  179. /package/dist/{Witness/Witness.d.ts → node/Witness/Witness.d.mts} +0 -0
  180. /package/dist/{Witness/ffmpeg/fluent/getVideoFrameAsImageFluent.d.mts → node/Witness/ffmpeg/fluent/getVideoFrameAsImageFluent.d.cts} +0 -0
  181. /package/dist/{Witness/ffmpeg/fluent/getVideoFrameAsImageFluent.d.ts → node/Witness/ffmpeg/fluent/getVideoFrameAsImageFluent.d.mts} +0 -0
  182. /package/dist/{Witness/ffmpeg/fluent/index.d.mts → node/Witness/ffmpeg/fluent/index.d.cts} +0 -0
  183. /package/dist/{Witness/ffmpeg/fluent/index.d.ts → node/Witness/ffmpeg/fluent/index.d.mts} +0 -0
  184. /package/dist/{Witness/ffmpeg/index.d.mts → node/Witness/ffmpeg/index.d.cts} +0 -0
  185. /package/dist/{Witness/ffmpeg/index.d.ts → node/Witness/ffmpeg/index.d.mts} +0 -0
  186. /package/dist/{Witness/ffmpeg/spawn/executeFfmpeg.d.mts → node/Witness/ffmpeg/spawn/executeFfmpeg.d.cts} +0 -0
  187. /package/dist/{Witness/ffmpeg/spawn/executeFfmpeg.d.ts → node/Witness/ffmpeg/spawn/executeFfmpeg.d.mts} +0 -0
  188. /package/dist/{Witness/ffmpeg/spawn/getVideoFrameAsImage.d.mts → node/Witness/ffmpeg/spawn/getVideoFrameAsImage.d.cts} +0 -0
  189. /package/dist/{Witness/ffmpeg/spawn/getVideoFrameAsImage.d.ts → node/Witness/ffmpeg/spawn/getVideoFrameAsImage.d.mts} +0 -0
  190. /package/dist/{Witness/ffmpeg/spawn/index.d.mts → node/Witness/ffmpeg/spawn/index.d.cts} +0 -0
  191. /package/dist/{Witness/ffmpeg/spawn/index.d.ts → node/Witness/ffmpeg/spawn/index.d.mts} +0 -0
  192. /package/dist/{Witness/index.d.mts → node/Witness/index.d.cts} +0 -0
  193. /package/dist/{Witness/index.d.ts → node/Witness/index.d.mts} +0 -0
  194. /package/dist/{index.d.mts → node/index.d.cts} +0 -0
  195. /package/dist/{index.d.ts → node/index.d.mts} +0 -0
@@ -0,0 +1,325 @@
1
+ // src/Witness/Config.ts
2
+ import { ImageThumbnailSchema } from "@xyo-network/image-thumbnail-payload-plugin";
3
+ var ImageThumbnailWitnessConfigSchema = `${ImageThumbnailSchema}.witness.config`;
4
+
5
+ // src/Witness/Witness.ts
6
+ import { promises as dnsPromises } from "node:dns";
7
+ import { compact } from "@xylabs/lodash";
8
+ import { URL } from "@xylabs/url";
9
+ import { axios } from "@xyo-network/axios";
10
+ import { PayloadHasher } from "@xyo-network/core";
11
+ import { ImageThumbnailSchema as ImageThumbnailSchema2 } from "@xyo-network/image-thumbnail-payload-plugin";
12
+ import { UrlSchema } from "@xyo-network/url-payload-plugin";
13
+ import { AbstractWitness } from "@xyo-network/witness";
14
+ import { Semaphore } from "async-mutex";
15
+ import FileType from "file-type";
16
+ import graphicsMagick from "gm";
17
+ import hasbin from "hasbin";
18
+ import { sha256 } from "hash-wasm";
19
+ import { LRUCache } from "lru-cache";
20
+ import shajs from "sha.js";
21
+ import Url from "url-parse";
22
+
23
+ // src/Witness/ffmpeg/fluent/getVideoFrameAsImageFluent.ts
24
+ import { uuid } from "@xyo-network/core";
25
+ import ffmpeg from "fluent-ffmpeg";
26
+ import { unlink, writeFile } from "fs/promises";
27
+ import { tmpdir } from "os";
28
+ import { Writable } from "stream";
29
+ var FfmpegOutputStream = class extends Writable {
30
+ chunks = [];
31
+ constructor(options) {
32
+ super(options);
33
+ }
34
+ _write(chunk, _encoding, callback) {
35
+ this.chunks.push(chunk);
36
+ callback();
37
+ }
38
+ /**
39
+ * Collects the output from ffmpeg into a buffer.
40
+ * @returns A buffer containing the concatenated
41
+ * output from ffmpeg.
42
+ */
43
+ toBuffer = () => Buffer.concat(this.chunks);
44
+ };
45
+ var getVideoFrameAsImageFluent = async (videoBuffer) => {
46
+ const tmpFile = `/${tmpdir()}/${uuid()}`;
47
+ try {
48
+ await writeFile(tmpFile, videoBuffer, { encoding: "binary" });
49
+ const imageBuffer = await new Promise((resolve, reject) => {
50
+ const ffmpegOutput = new FfmpegOutputStream();
51
+ ffmpeg().on("error", (err) => reject(err.message)).on("end", () => resolve(ffmpegOutput.toBuffer())).input(tmpFile).takeFrames(1).withNoAudio().outputOptions("-f image2pipe").videoCodec("png").pipe(ffmpegOutput);
52
+ });
53
+ return imageBuffer;
54
+ } finally {
55
+ try {
56
+ await unlink(tmpFile);
57
+ } catch {
58
+ }
59
+ }
60
+ };
61
+
62
+ // src/Witness/Witness.ts
63
+ var gm = graphicsMagick.subClass({ imageMagick: "7+" });
64
+ var ImageThumbnailWitness = class _ImageThumbnailWitness extends AbstractWitness {
65
+ static configSchemas = [ImageThumbnailWitnessConfigSchema];
66
+ _cache;
67
+ _semaphore = new Semaphore(this.maxAsyncProcesses);
68
+ get cache() {
69
+ this._cache = this._cache ?? new LRUCache({
70
+ max: this.maxCacheEntries,
71
+ maxSize: this.maxCacheBytes,
72
+ //just returning the size of the data
73
+ sizeCalculation: (value) => {
74
+ var _a;
75
+ return ((_a = value.url) == null ? void 0 : _a.length) ?? 1;
76
+ }
77
+ });
78
+ return this._cache;
79
+ }
80
+ get encoding() {
81
+ return this.config.encoding ?? "PNG";
82
+ }
83
+ get height() {
84
+ return this.config.height ?? 128;
85
+ }
86
+ get ipfGateway() {
87
+ return this.config.ipfsGateway ?? "5d7b6582.beta.decentralnetworkservices.com";
88
+ }
89
+ get maxAsyncProcesses() {
90
+ return this.config.maxAsyncProcesses ?? 2;
91
+ }
92
+ get maxCacheBytes() {
93
+ return this.config.maxCacheBytes ?? 1024 * 1024 * 16;
94
+ }
95
+ get maxCacheEntries() {
96
+ return this.config.maxCacheEntries ?? 500;
97
+ }
98
+ get quality() {
99
+ return this.config.quality ?? 50;
100
+ }
101
+ get width() {
102
+ return this.config.width ?? 128;
103
+ }
104
+ static async binaryToSha256(data) {
105
+ await PayloadHasher.wasmInitialized;
106
+ if (PayloadHasher.wasmSupport.canUseWasm) {
107
+ try {
108
+ return await sha256(data);
109
+ } catch (ex) {
110
+ PayloadHasher.wasmSupport.allowWasm = false;
111
+ }
112
+ }
113
+ return shajs("sha256").update(data).digest().toString();
114
+ }
115
+ static bufferFromDataUrl(url) {
116
+ if (url.startsWith("data:image")) {
117
+ const data = url.split(",")[1];
118
+ if (data) {
119
+ return Buffer.from(Uint8Array.from(atob(data), (c) => c.charCodeAt(0)));
120
+ } else {
121
+ const error = {
122
+ message: "Invalid data Url",
123
+ name: "ImageThumbnailWitnessError",
124
+ url
125
+ };
126
+ throw error;
127
+ }
128
+ }
129
+ }
130
+ /**
131
+ * Returns the equivalent IPFS gateway URL for the supplied URL.
132
+ * @param urlToCheck The URL to check
133
+ * @returns If the supplied URL is an IPFS URL, it converts the URL to the
134
+ * equivalent IPFS gateway URL. Otherwise, returns the original URL.
135
+ */
136
+ checkIpfsUrl(urlToCheck) {
137
+ const url = new URL(urlToCheck);
138
+ let protocol = url.protocol;
139
+ let host = url.host;
140
+ let path = url.pathname;
141
+ const query = url.search;
142
+ if (protocol === "ipfs:") {
143
+ protocol = "https:";
144
+ host = this.ipfGateway;
145
+ path = url.host === "ipfs" ? `ipfs${path}` : `ipfs/${url.host}${path}`;
146
+ const root = `${protocol}//${host}/${path}`;
147
+ return (query == null ? void 0 : query.length) > 0 ? `${root}?${query}` : root;
148
+ } else {
149
+ return urlToCheck;
150
+ }
151
+ }
152
+ async observeHandler(payloads = []) {
153
+ if (!hasbin.sync("magick")) {
154
+ throw Error("ImageMagick is required for this witness");
155
+ }
156
+ const urlPayloads = payloads.filter((payload) => payload.schema === UrlSchema);
157
+ return await this._semaphore.runExclusive(
158
+ async () => compact(
159
+ await Promise.all(
160
+ urlPayloads.map(async ({ url }) => {
161
+ const cachedResult = this.cache.get(url);
162
+ if (cachedResult) {
163
+ return cachedResult;
164
+ }
165
+ let result;
166
+ const dataBuffer = _ImageThumbnailWitness.bufferFromDataUrl(url);
167
+ if (dataBuffer) {
168
+ result = {
169
+ schema: ImageThumbnailSchema2,
170
+ sourceHash: await _ImageThumbnailWitness.binaryToSha256(dataBuffer),
171
+ sourceUrl: url,
172
+ url
173
+ };
174
+ } else {
175
+ const mutatedUrl = this.checkIpfsUrl(url);
176
+ result = await this.fromHttp(mutatedUrl, url);
177
+ }
178
+ this.cache.set(url, result);
179
+ return result;
180
+ })
181
+ )
182
+ )
183
+ );
184
+ }
185
+ async createThumbnailDataUrl(sourceBuffer, encoding) {
186
+ const thumb = await new Promise((resolve, reject) => {
187
+ gm(sourceBuffer).quality(this.quality).resize(this.width, this.height).flatten().toBuffer(encoding ?? this.encoding, (error, buffer) => {
188
+ if (error) {
189
+ reject(error);
190
+ } else {
191
+ resolve(buffer);
192
+ }
193
+ });
194
+ });
195
+ return `data:image/png;base64,${thumb.toString("base64")}`;
196
+ }
197
+ /**
198
+ * Creates an image thumbnail from a video.
199
+ * @param videoBuffer The input video buffer.
200
+ * @returns An buffer containing an image thumbnail for the video.
201
+ */
202
+ async createThumbnailFromVideo(videoBuffer) {
203
+ const imageBuffer = await getVideoFrameAsImageFluent(videoBuffer);
204
+ return this.createThumbnailDataUrl(imageBuffer);
205
+ }
206
+ async fromHttp(url, sourceUrl) {
207
+ var _a, _b, _c, _d, _e, _f;
208
+ let response;
209
+ let dnsResult;
210
+ try {
211
+ const urlObj = new Url(url);
212
+ dnsResult = await dnsPromises.resolve(urlObj.host);
213
+ } catch (ex) {
214
+ const error = ex;
215
+ const result2 = {
216
+ http: {
217
+ dnsError: error.code
218
+ },
219
+ schema: ImageThumbnailSchema2,
220
+ sourceUrl: sourceUrl ?? url
221
+ };
222
+ return result2;
223
+ }
224
+ try {
225
+ response = await axios.get(url, {
226
+ responseType: "arraybuffer"
227
+ });
228
+ } catch (ex) {
229
+ const axiosError = ex;
230
+ if (axiosError.isAxiosError) {
231
+ const result2 = {
232
+ http: {
233
+ ipAddress: dnsResult[0],
234
+ status: (_a = axiosError == null ? void 0 : axiosError.response) == null ? void 0 : _a.status
235
+ },
236
+ schema: ImageThumbnailSchema2,
237
+ sourceUrl: sourceUrl ?? url
238
+ };
239
+ return result2;
240
+ } else {
241
+ throw ex;
242
+ }
243
+ }
244
+ const result = {
245
+ http: {
246
+ status: response.status
247
+ },
248
+ schema: ImageThumbnailSchema2,
249
+ sourceUrl: sourceUrl ?? url
250
+ };
251
+ if (response.status >= 200 && response.status < 300) {
252
+ const contentType = (_b = response.headers["content-type"]) == null ? void 0 : _b.toString();
253
+ const [mediaType, fileType] = contentType.split("/");
254
+ result.mime = result.mime ?? {};
255
+ result.mime.returned = mediaType;
256
+ const sourceBuffer = Buffer.from(response.data, "binary");
257
+ try {
258
+ result.mime.detected = await FileType.fromBuffer(sourceBuffer);
259
+ } catch (ex) {
260
+ const error = ex;
261
+ (_c = this.logger) == null ? void 0 : _c.error(`FileType error: ${error.message}`);
262
+ }
263
+ const processImage = async (encoding2) => {
264
+ result.sourceHash = await _ImageThumbnailWitness.binaryToSha256(sourceBuffer);
265
+ result.url = await this.createThumbnailDataUrl(sourceBuffer, encoding2);
266
+ };
267
+ const processVideo = async () => {
268
+ if (hasbin.sync("ffmpeg")) {
269
+ result.sourceHash = await _ImageThumbnailWitness.binaryToSha256(sourceBuffer);
270
+ result.url = await this.createThumbnailFromVideo(sourceBuffer);
271
+ } else {
272
+ result.mime = result.mime ?? {};
273
+ result.mime.invalid = true;
274
+ }
275
+ };
276
+ let encoding = "PNG";
277
+ switch (fileType.toUpperCase()) {
278
+ case "GIF":
279
+ encoding = "GIF";
280
+ break;
281
+ case "JPG":
282
+ case "JPEG":
283
+ encoding = "JPG";
284
+ break;
285
+ }
286
+ switch (mediaType) {
287
+ case "image": {
288
+ await processImage(encoding);
289
+ result.mime.type = mediaType;
290
+ break;
291
+ }
292
+ case "video": {
293
+ await processVideo();
294
+ result.mime.type = mediaType;
295
+ break;
296
+ }
297
+ default: {
298
+ switch ((_d = result.mime.detected) == null ? void 0 : _d.mime) {
299
+ case "image": {
300
+ await processImage();
301
+ result.mime.type = (_e = result.mime.detected) == null ? void 0 : _e.mime;
302
+ break;
303
+ }
304
+ case "video": {
305
+ await processVideo();
306
+ result.mime.type = (_f = result.mime.detected) == null ? void 0 : _f.mime;
307
+ break;
308
+ }
309
+ default: {
310
+ result.mime.invalid = true;
311
+ break;
312
+ }
313
+ }
314
+ break;
315
+ }
316
+ }
317
+ }
318
+ return result;
319
+ }
320
+ };
321
+ export {
322
+ ImageThumbnailWitness,
323
+ ImageThumbnailWitnessConfigSchema
324
+ };
325
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/Witness/Config.ts","../../../src/Witness/Witness.ts","../../../src/Witness/ffmpeg/fluent/getVideoFrameAsImageFluent.ts"],"sourcesContent":["import { ImageThumbnailSchema } from '@xyo-network/image-thumbnail-payload-plugin'\nimport { WitnessConfig } from '@xyo-network/witness'\n\nexport const ImageThumbnailWitnessConfigSchema = `${ImageThumbnailSchema}.witness.config` as const\nexport type ImageThumbnailWitnessConfigSchema = typeof ImageThumbnailWitnessConfigSchema\n\nexport type ImageThumbnailEncoding = 'PNG' | 'JPG' | 'GIF'\n\nexport type ImageThumbnailWitnessConfig = WitnessConfig<{\n encoding?: ImageThumbnailEncoding\n height?: number\n ipfsGateway?: string\n maxAsyncProcesses?: number\n maxCacheBytes?: number\n maxCacheEntries?: number\n quality?: number\n schema: ImageThumbnailWitnessConfigSchema\n width?: number\n}>\n","/* eslint-disable max-statements */\nimport { promises as dnsPromises } from 'node:dns'\n\nimport { compact } from '@xylabs/lodash'\nimport { URL } from '@xylabs/url'\nimport { axios, AxiosError, AxiosResponse } from '@xyo-network/axios'\nimport { PayloadHasher } from '@xyo-network/core'\nimport { ImageThumbnail, ImageThumbnailSchema } from '@xyo-network/image-thumbnail-payload-plugin'\nimport { UrlPayload, UrlSchema } from '@xyo-network/url-payload-plugin'\nimport { AbstractWitness } from '@xyo-network/witness'\nimport { Semaphore } from 'async-mutex'\nimport FileType from 'file-type'\nimport graphicsMagick from 'gm'\nimport hasbin from 'hasbin'\nimport { sha256 } from 'hash-wasm'\nimport { LRUCache } from 'lru-cache'\nimport shajs from 'sha.js'\nimport Url from 'url-parse'\n\nimport { ImageThumbnailEncoding, ImageThumbnailWitnessConfigSchema } from './Config'\nimport { getVideoFrameAsImageFluent } from './ffmpeg'\nimport { ImageThumbnailWitnessParams } from './Params'\n\n//TODO: Break this into two Witnesses?\n\n// setFfmpegPath(ffmpegPath)\n\n// eslint-disable-next-line import/no-named-as-default-member\nconst gm = graphicsMagick.subClass({ imageMagick: '7+' })\n\nexport interface ImageThumbnailWitnessError extends Error {\n name: 'ImageThumbnailWitnessError'\n url: string\n}\n\nexport interface DnsError extends Error {\n code: string\n}\n\nexport class ImageThumbnailWitness<TParams extends ImageThumbnailWitnessParams = ImageThumbnailWitnessParams> extends AbstractWitness<TParams> {\n static override configSchemas = [ImageThumbnailWitnessConfigSchema]\n\n private _cache?: LRUCache<string, ImageThumbnail>\n private _semaphore = new Semaphore(this.maxAsyncProcesses)\n\n get cache() {\n this._cache =\n this._cache ??\n new LRUCache<string, ImageThumbnail>({\n max: this.maxCacheEntries,\n maxSize: this.maxCacheBytes,\n //just returning the size of the data\n sizeCalculation: (value) => value.url?.length ?? 1,\n })\n return this._cache\n }\n\n get encoding() {\n return this.config.encoding ?? 'PNG'\n }\n\n get height() {\n return this.config.height ?? 128\n }\n\n get ipfGateway() {\n return this.config.ipfsGateway ?? '5d7b6582.beta.decentralnetworkservices.com'\n }\n\n get maxAsyncProcesses() {\n return this.config.maxAsyncProcesses ?? 2\n }\n\n get maxCacheBytes() {\n return this.config.maxCacheBytes ?? 1024 * 1024 * 16 //64MB max size\n }\n\n get maxCacheEntries() {\n return this.config.maxCacheEntries ?? 500\n }\n\n get quality() {\n return this.config.quality ?? 50\n }\n\n get width() {\n return this.config.width ?? 128\n }\n\n private static async binaryToSha256(data: Uint8Array) {\n await PayloadHasher.wasmInitialized\n if (PayloadHasher.wasmSupport.canUseWasm) {\n try {\n return await sha256(data)\n } catch (ex) {\n PayloadHasher.wasmSupport.allowWasm = false\n }\n }\n\n return shajs('sha256').update(data).digest().toString()\n }\n\n private static bufferFromDataUrl(url: string): Buffer | undefined {\n if (url.startsWith('data:image')) {\n const data = url.split(',')[1]\n if (data) {\n return Buffer.from(Uint8Array.from(atob(data), (c) => c.charCodeAt(0)))\n } else {\n const error: ImageThumbnailWitnessError = {\n message: 'Invalid data Url',\n name: 'ImageThumbnailWitnessError',\n url,\n }\n throw error\n }\n }\n }\n\n /**\n * Returns the equivalent IPFS gateway URL for the supplied URL.\n * @param urlToCheck The URL to check\n * @returns If the supplied URL is an IPFS URL, it converts the URL to the\n * equivalent IPFS gateway URL. Otherwise, returns the original URL.\n */\n checkIpfsUrl(urlToCheck: string) {\n const url = new URL(urlToCheck)\n let protocol = url.protocol\n let host = url.host\n let path = url.pathname\n const query = url.search\n if (protocol === 'ipfs:') {\n protocol = 'https:'\n host = this.ipfGateway\n path = url.host === 'ipfs' ? `ipfs${path}` : `ipfs/${url.host}${path}`\n const root = `${protocol}//${host}/${path}`\n return query?.length > 0 ? `${root}?${query}` : root\n } else {\n return urlToCheck\n }\n }\n\n protected override async observeHandler(payloads: UrlPayload[] = []): Promise<ImageThumbnail[]> {\n // eslint-disable-next-line import/no-named-as-default-member\n if (!hasbin.sync('magick')) {\n throw Error('ImageMagick is required for this witness')\n }\n const urlPayloads = payloads.filter((payload) => payload.schema === UrlSchema)\n return await this._semaphore.runExclusive(async () =>\n compact(\n await Promise.all(\n urlPayloads.map<Promise<ImageThumbnail>>(async ({ url }) => {\n const cachedResult = this.cache.get(url)\n if (cachedResult) {\n return cachedResult\n }\n let result: ImageThumbnail\n\n //if it is a data URL, return a Buffer\n const dataBuffer = ImageThumbnailWitness.bufferFromDataUrl(url)\n\n if (dataBuffer) {\n result = {\n schema: ImageThumbnailSchema,\n sourceHash: await ImageThumbnailWitness.binaryToSha256(dataBuffer),\n sourceUrl: url,\n url,\n }\n } else {\n //if it is ipfs, go through cloud flair\n const mutatedUrl = this.checkIpfsUrl(url)\n result = await this.fromHttp(mutatedUrl, url)\n }\n this.cache.set(url, result)\n return result\n }),\n ),\n ),\n )\n }\n\n private async createThumbnailDataUrl(sourceBuffer: Buffer, encoding?: ImageThumbnailEncoding) {\n const thumb = await new Promise<Buffer>((resolve, reject) => {\n gm(sourceBuffer)\n .quality(this.quality)\n .resize(this.width, this.height)\n .flatten()\n .toBuffer(encoding ?? this.encoding, (error, buffer) => {\n if (error) {\n reject(error)\n } else {\n resolve(buffer)\n }\n })\n })\n return `data:image/png;base64,${thumb.toString('base64')}`\n }\n\n /**\n * Creates an image thumbnail from a video.\n * @param videoBuffer The input video buffer.\n * @returns An buffer containing an image thumbnail for the video.\n */\n private async createThumbnailFromVideo(videoBuffer: Buffer) {\n const imageBuffer = await getVideoFrameAsImageFluent(videoBuffer)\n return this.createThumbnailDataUrl(imageBuffer)\n }\n\n private async fromHttp(url: string, sourceUrl?: string): Promise<ImageThumbnail> {\n let response: AxiosResponse\n let dnsResult: string[]\n try {\n const urlObj = new Url(url)\n dnsResult = await dnsPromises.resolve(urlObj.host)\n // console.log(`dnsResult: ${JSON.stringify(dnsResult, null, 2)}`)\n } catch (ex) {\n const error = ex as DnsError\n const result: ImageThumbnail = {\n http: {\n dnsError: error.code,\n },\n schema: ImageThumbnailSchema,\n sourceUrl: sourceUrl ?? url,\n }\n return result\n }\n try {\n response = await axios.get(url, {\n responseType: 'arraybuffer',\n })\n } catch (ex) {\n const axiosError = ex as AxiosError\n if (axiosError.isAxiosError) {\n //selectively pick fields from AxiosError\n const result: ImageThumbnail = {\n http: {\n ipAddress: dnsResult[0],\n status: axiosError?.response?.status,\n },\n schema: ImageThumbnailSchema,\n sourceUrl: sourceUrl ?? url,\n }\n return result\n } else {\n throw ex\n }\n }\n\n const result: ImageThumbnail = {\n http: {\n status: response.status,\n },\n schema: ImageThumbnailSchema,\n sourceUrl: sourceUrl ?? url,\n }\n\n if (response.status >= 200 && response.status < 300) {\n const contentType: string = response.headers['content-type']?.toString()\n const [mediaType, fileType] = contentType.split('/')\n result.mime = result.mime ?? {}\n result.mime.returned = mediaType\n const sourceBuffer = Buffer.from(response.data, 'binary')\n\n try {\n result.mime.detected = await FileType.fromBuffer(sourceBuffer)\n } catch (ex) {\n const error = ex as Error\n this.logger?.error(`FileType error: ${error.message}`)\n }\n\n const processImage = async (encoding?: ImageThumbnailEncoding) => {\n result.sourceHash = await ImageThumbnailWitness.binaryToSha256(sourceBuffer)\n result.url = await this.createThumbnailDataUrl(sourceBuffer, encoding)\n }\n\n const processVideo = async () => {\n // Gracefully handle the case where ffmpeg is not installed.\n // eslint-disable-next-line import/no-named-as-default-member\n if (hasbin.sync('ffmpeg')) {\n result.sourceHash = await ImageThumbnailWitness.binaryToSha256(sourceBuffer)\n result.url = await this.createThumbnailFromVideo(sourceBuffer)\n } else {\n result.mime = result.mime ?? {}\n result.mime.invalid = true\n }\n }\n\n let encoding: ImageThumbnailEncoding = 'PNG'\n\n switch (fileType.toUpperCase()) {\n case 'GIF':\n encoding = 'GIF'\n break\n case 'JPG':\n case 'JPEG':\n encoding = 'JPG'\n break\n }\n\n switch (mediaType) {\n case 'image': {\n await processImage(encoding)\n result.mime.type = mediaType\n break\n }\n case 'video': {\n await processVideo()\n result.mime.type = mediaType\n break\n }\n default: {\n switch (result.mime.detected?.mime) {\n case 'image': {\n await processImage()\n result.mime.type = result.mime.detected?.mime\n break\n }\n case 'video': {\n await processVideo()\n result.mime.type = result.mime.detected?.mime\n break\n }\n default: {\n result.mime.invalid = true\n break\n }\n }\n break\n }\n }\n }\n return result\n }\n}\n","import { uuid } from '@xyo-network/core'\nimport ffmpeg from 'fluent-ffmpeg'\nimport { unlink, writeFile } from 'fs/promises'\nimport { tmpdir } from 'os'\nimport { Writable, WritableOptions } from 'stream'\n\n/**\n * A Writable stream that collects output from ffmpeg.\n */\nclass FfmpegOutputStream extends Writable {\n private readonly chunks: Uint8Array[] = []\n\n constructor(options?: WritableOptions) {\n super(options)\n }\n\n override _write(chunk: never, _encoding: BufferEncoding, callback: (error?: Error | null) => void): void {\n this.chunks.push(chunk)\n callback()\n }\n\n /**\n * Collects the output from ffmpeg into a buffer.\n * @returns A buffer containing the concatenated\n * output from ffmpeg.\n */\n toBuffer = () => Buffer.concat(this.chunks)\n}\n\n/**\n * Execute FFmpeg using fluent API with provided input buffer and video thumbnail image.\n * @param videoBuffer Input video buffer.\n * @returns Output buffer containing the video thumbnail image.\n */\nexport const getVideoFrameAsImageFluent = async (videoBuffer: Buffer) => {\n // Get a temp file name\n const tmpFile = `/${tmpdir()}/${uuid()}`\n try {\n // Write videoBuffer to temp file for use as input to ffmpeg to\n // avoid issues with ffmpeg inferring premature EOF from buffer\n // passed via stdin (happens when ffmpeg is trying to infer\n // input video format)\n await writeFile(tmpFile, videoBuffer, { encoding: 'binary' })\n const imageBuffer = await new Promise<Buffer>((resolve, reject) => {\n // Create a Writable stream to collect PNG output from ffmpeg\n const ffmpegOutput = new FfmpegOutputStream()\n // Execute ffmpeg using fluent API\n ffmpeg()\n // NOTE: Uncomment to debug CLI args to ffmpeg\n // .on('start', (commandLine) => console.log('Spawned Ffmpeg with command: ' + commandLine))\n .on('error', (err) => reject(err.message))\n // Listen for the 'end' event to combine the output into a buffer holding the PNG image\n .on('end', () => resolve(ffmpegOutput.toBuffer()))\n .input(tmpFile) // Use temp file as input\n .takeFrames(1) // Only take 1st video frame\n .withNoAudio() // Don't include audio\n .outputOptions('-f image2pipe') // Write output to stdout\n .videoCodec('png') // Force PNG output\n // Start processing and direct ffmpeg stdout to writable stream\n .pipe(ffmpegOutput)\n })\n return imageBuffer\n } finally {\n // Cleanup temp file\n try {\n await unlink(tmpFile)\n } catch {\n // No error here since file doesn't exist\n }\n }\n}\n"],"mappings":"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","names":["ImageThumbnailSchema","ImageThumbnailSchema","result","encoding"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAE/C,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AAEzB,OAAO,EAAE,oBAAoB,EAAE,CAAA;AAG/B,eAAe,oBAAoB,CAAA"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAE/C,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AAEzB,OAAO,EAAE,oBAAoB,EAAE,CAAA;AAG/B,eAAe,oBAAoB,CAAA"}
@@ -0,0 +1,6 @@
1
+ import { ImageThumbnailPlugin } from './Plugin';
2
+ export * from './Diviner';
3
+ export * from './Witness';
4
+ export { ImageThumbnailPlugin };
5
+ export default ImageThumbnailPlugin;
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAE/C,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AAEzB,OAAO,EAAE,oBAAoB,EAAE,CAAA;AAG/B,eAAe,oBAAoB,CAAA"}
@@ -110,7 +110,7 @@ var ImageThumbnailDiviner = class extends import_abstract_diviner.AbstractDivine
110
110
  const urls = payloads.map((urlPayload) => urlPayload.url);
111
111
  const map = await this.getSafeMap();
112
112
  const archivist = await this.getArchivistInstance();
113
- const hashes = (0, import_lodash.compact)(urls.map((url) => map?.[url]));
113
+ const hashes = (0, import_lodash.compact)(urls.map((url) => map == null ? void 0 : map[url]));
114
114
  return (await archivist.get(hashes)).filter((payload) => payload.schema === import_image_thumbnail_payload_plugin2.ImageThumbnailSchema);
115
115
  }
116
116
  //using promise as mutex
@@ -133,10 +133,11 @@ var ImageThumbnailDiviner = class extends import_abstract_diviner.AbstractDivine
133
133
  }
134
134
  }
135
135
  async loadMapWithAll() {
136
+ var _a;
136
137
  if (await this.started()) {
137
138
  const archivist = await this.getArchivistInstance();
138
139
  (0, import_assert.assertEx)(archivist.all, "Archivist does not support 'all'");
139
- const allPayloads = await archivist.all?.() ?? [];
140
+ const allPayloads = await ((_a = archivist.all) == null ? void 0 : _a.call(archivist)) ?? [];
140
141
  const imagePayloadPairs = await Promise.all(
141
142
  allPayloads.filter((payload) => payload.schema === import_image_thumbnail_payload_plugin2.ImageThumbnailSchema).map(async (payload) => [await import_core.PayloadHasher.hashAsync(payload), payload])
142
143
  );
@@ -292,7 +293,10 @@ var ImageThumbnailWitness = class _ImageThumbnailWitness extends import_witness.
292
293
  max: this.maxCacheEntries,
293
294
  maxSize: this.maxCacheBytes,
294
295
  //just returning the size of the data
295
- sizeCalculation: (value) => value.url?.length ?? 1
296
+ sizeCalculation: (value) => {
297
+ var _a;
298
+ return ((_a = value.url) == null ? void 0 : _a.length) ?? 1;
299
+ }
296
300
  });
297
301
  return this._cache;
298
302
  }
@@ -363,7 +367,7 @@ var ImageThumbnailWitness = class _ImageThumbnailWitness extends import_witness.
363
367
  host = this.ipfGateway;
364
368
  path = url.host === "ipfs" ? `ipfs${path}` : `ipfs/${url.host}${path}`;
365
369
  const root = `${protocol}//${host}/${path}`;
366
- return query?.length > 0 ? `${root}?${query}` : root;
370
+ return (query == null ? void 0 : query.length) > 0 ? `${root}?${query}` : root;
367
371
  } else {
368
372
  return urlToCheck;
369
373
  }
@@ -423,6 +427,7 @@ var ImageThumbnailWitness = class _ImageThumbnailWitness extends import_witness.
423
427
  return this.createThumbnailDataUrl(imageBuffer);
424
428
  }
425
429
  async fromHttp(url, sourceUrl) {
430
+ var _a, _b, _c, _d, _e, _f;
426
431
  let response;
427
432
  let dnsResult;
428
433
  try {
@@ -449,7 +454,7 @@ var ImageThumbnailWitness = class _ImageThumbnailWitness extends import_witness.
449
454
  const result2 = {
450
455
  http: {
451
456
  ipAddress: dnsResult[0],
452
- status: axiosError?.response?.status
457
+ status: (_a = axiosError == null ? void 0 : axiosError.response) == null ? void 0 : _a.status
453
458
  },
454
459
  schema: import_image_thumbnail_payload_plugin4.ImageThumbnailSchema,
455
460
  sourceUrl: sourceUrl ?? url
@@ -467,7 +472,7 @@ var ImageThumbnailWitness = class _ImageThumbnailWitness extends import_witness.
467
472
  sourceUrl: sourceUrl ?? url
468
473
  };
469
474
  if (response.status >= 200 && response.status < 300) {
470
- const contentType = response.headers["content-type"]?.toString();
475
+ const contentType = (_b = response.headers["content-type"]) == null ? void 0 : _b.toString();
471
476
  const [mediaType, fileType] = contentType.split("/");
472
477
  result.mime = result.mime ?? {};
473
478
  result.mime.returned = mediaType;
@@ -476,7 +481,7 @@ var ImageThumbnailWitness = class _ImageThumbnailWitness extends import_witness.
476
481
  result.mime.detected = await import_file_type.default.fromBuffer(sourceBuffer);
477
482
  } catch (ex) {
478
483
  const error = ex;
479
- this.logger?.error(`FileType error: ${error.message}`);
484
+ (_c = this.logger) == null ? void 0 : _c.error(`FileType error: ${error.message}`);
480
485
  }
481
486
  const processImage = async (encoding2) => {
482
487
  result.sourceHash = await _ImageThumbnailWitness.binaryToSha256(sourceBuffer);
@@ -513,15 +518,15 @@ var ImageThumbnailWitness = class _ImageThumbnailWitness extends import_witness.
513
518
  break;
514
519
  }
515
520
  default: {
516
- switch (result.mime.detected?.mime) {
521
+ switch ((_d = result.mime.detected) == null ? void 0 : _d.mime) {
517
522
  case "image": {
518
523
  await processImage();
519
- result.mime.type = result.mime.detected?.mime;
524
+ result.mime.type = (_e = result.mime.detected) == null ? void 0 : _e.mime;
520
525
  break;
521
526
  }
522
527
  case "video": {
523
528
  await processVideo();
524
- result.mime.type = result.mime.detected?.mime;
529
+ result.mime.type = (_f = result.mime.detected) == null ? void 0 : _f.mime;
525
530
  break;
526
531
  }
527
532
  default: {
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/index.ts","../../src/Plugin.ts","../../src/Diviner/Config.ts","../../src/Diviner/Diviner.ts","../../src/Witness/Config.ts","../../src/Witness/Witness.ts","../../src/Witness/ffmpeg/fluent/getVideoFrameAsImageFluent.ts"],"sourcesContent":["import { ImageThumbnailPlugin } from './Plugin'\n\nexport * from './Diviner'\nexport * from './Witness'\n\nexport { ImageThumbnailPlugin }\n\n// eslint-disable-next-line import/no-default-export\nexport default ImageThumbnailPlugin\n","import { ImageThumbnailSchema } from '@xyo-network/image-thumbnail-payload-plugin'\nimport { PayloadSetSchema } from '@xyo-network/payload-model'\nimport { createPayloadSetDualPlugin } from '@xyo-network/payloadset-plugin'\n\nimport { ImageThumbnailDiviner } from './Diviner'\nimport { ImageThumbnailWitness } from './Witness'\n\nexport const ImageThumbnailPlugin = () =>\n createPayloadSetDualPlugin<ImageThumbnailWitness, ImageThumbnailDiviner>(\n { required: { [ImageThumbnailSchema]: 1 }, schema: PayloadSetSchema },\n {\n diviner: async (params) => {\n const result = await ImageThumbnailDiviner.create(params)\n return result\n },\n witness: async (params) => {\n const result = await ImageThumbnailWitness.create(params)\n return result\n },\n },\n )\n","import { DivinerConfig } from '@xyo-network/diviner-model'\nimport { ImageThumbnailSchema } from '@xyo-network/image-thumbnail-payload-plugin'\n\nexport const ImageThumbnailDivinerConfigSchema = `${ImageThumbnailSchema}.diviner.config` as const\nexport type ImageThumbnailDivinerConfigSchema = typeof ImageThumbnailDivinerConfigSchema\n\nexport type ImageThumbnailDivinerConfig = DivinerConfig<{\n archivist?: string\n payloadDiviner?: string\n payloadDivinerLimit?: number\n pollFrequency?: number\n schema: ImageThumbnailDivinerConfigSchema\n}>\n","import { assertEx } from '@xylabs/assert'\nimport { delay } from '@xylabs/delay'\nimport { compact } from '@xylabs/lodash'\nimport { AbstractDiviner } from '@xyo-network/abstract-diviner'\nimport { ArchivistInstance, asArchivistInstance } from '@xyo-network/archivist-model'\nimport { PayloadHasher } from '@xyo-network/core'\nimport { asDivinerInstance, DivinerConfigSchema, DivinerInstance } from '@xyo-network/diviner-model'\nimport { PayloadDivinerQueryPayload, PayloadDivinerQuerySchema } from '@xyo-network/diviner-payload-model'\nimport { ImageThumbnail, ImageThumbnailSchema } from '@xyo-network/image-thumbnail-payload-plugin'\nimport { UrlPayload } from '@xyo-network/url-payload-plugin'\n\nimport { ImageThumbnailDivinerConfigSchema } from './Config'\nimport { ImageThumbnailDivinerParams } from './Params'\n\nexport class ImageThumbnailDiviner<TParams extends ImageThumbnailDivinerParams = ImageThumbnailDivinerParams> extends AbstractDiviner<TParams> {\n static override configSchemas = [ImageThumbnailDivinerConfigSchema, DivinerConfigSchema]\n\n private _archivistInstance: Promise<ArchivistInstance> | undefined\n private _initializeArchivistConnectionIfNeededPromise: Promise<void> | undefined\n private _map: Record<string, string> | undefined\n private _payloadDivinerInstance: Promise<DivinerInstance> | undefined\n private _pollId?: string | number | NodeJS.Timeout\n\n // static override get configSchema() {\n // return ImageThumbnailDivinerConfigSchema\n // }\n\n get archivist() {\n return this.config.archivist\n }\n\n get payloadDiviner() {\n return this.config.payloadDiviner\n }\n\n get payloadDivinerLimit() {\n return this.config.payloadDivinerLimit ?? 10000\n }\n\n get pollFrequency() {\n return this.config.pollFrequency\n }\n\n //using promise as mutex\n async getArchivistInstance(): Promise<ArchivistInstance> {\n //if previously checked, but not found, clear promise\n if (this._archivistInstance && !(await this._archivistInstance)) {\n this._archivistInstance = undefined\n }\n this._archivistInstance =\n this._archivistInstance ??\n (async () => {\n const module = this.archivist ? await this.resolve(this.archivist) : undefined\n return asArchivistInstance(module, 'Provided archivist address did not resolve to an Archivist')\n })()\n return this._archivistInstance\n }\n\n //using promise as mutex\n async getPayloadDivinerInstance(): Promise<DivinerInstance | undefined> {\n const payloadDivinerAddress = this.payloadDiviner\n if (payloadDivinerAddress) {\n //if previously checked, but not found, clear promise\n if (this._payloadDivinerInstance && !(await this._payloadDivinerInstance)) {\n this._payloadDivinerInstance = undefined\n }\n this._payloadDivinerInstance =\n this._payloadDivinerInstance ??\n (async () => {\n const module = await this.resolve(payloadDivinerAddress)\n return asDivinerInstance(module, 'Provided payload diviner address did not resolve to a Diviner')\n })()\n\n return this._payloadDivinerInstance\n }\n }\n\n protected override async divineHandler(payloads: UrlPayload[] = []): Promise<ImageThumbnail[]> {\n await this.initializeArchivistConnectionIfNeeded()\n const urls = payloads.map((urlPayload) => urlPayload.url)\n const map = await this.getSafeMap()\n const archivist = await this.getArchivistInstance()\n const hashes = compact(urls.map((url) => map?.[url]))\n return (await archivist.get(hashes)).filter((payload): payload is ImageThumbnail => payload.schema === ImageThumbnailSchema)\n }\n\n //using promise as mutex\n protected initializeArchivistConnectionIfNeeded() {\n this._initializeArchivistConnectionIfNeededPromise =\n this._initializeArchivistConnectionIfNeededPromise ??\n (async () => {\n if (!this._map) {\n await this.attachArchivistEvents()\n console.log('initializeArchivistConnectionIfNeeded: attachArchivistEvents done')\n await this.poll()\n console.log('initializeArchivistConnectionIfNeeded: poll done')\n }\n })()\n return this._initializeArchivistConnectionIfNeededPromise\n }\n\n protected async loadMap() {\n if (this.payloadDiviner) {\n return await this.loadMapWithPayloadDiviner()\n } else {\n return await this.loadMapWithAll()\n }\n }\n\n protected async loadMapWithAll() {\n if (await this.started()) {\n const archivist = await this.getArchivistInstance()\n assertEx(archivist.all, \"Archivist does not support 'all'\")\n const allPayloads = (await archivist.all?.()) ?? []\n const imagePayloadPairs = await Promise.all(\n allPayloads\n .filter((payload): payload is ImageThumbnail => payload.schema === ImageThumbnailSchema)\n .map<Promise<[string, ImageThumbnail]>>(async (payload) => [await PayloadHasher.hashAsync(payload), payload]),\n )\n this._map = imagePayloadPairs.reduce<Record<string, string>>((prev, [hash, payload]) => {\n prev[payload.sourceUrl] = hash\n return prev\n }, {})\n }\n }\n\n protected async loadMapWithPayloadDiviner() {\n console.log('loadMapWithPayloadDiviner: started')\n if (await this.started()) {\n const diviner = await this.getPayloadDivinerInstance()\n let offset: number | undefined = undefined\n let moreAvailable = true\n if (diviner) {\n const newMap: Record<string, string> = {}\n while (moreAvailable) {\n const payloadDivinerQuery: PayloadDivinerQueryPayload = {\n limit: this.payloadDivinerLimit,\n offset,\n schema: PayloadDivinerQuerySchema,\n schemas: [ImageThumbnailSchema],\n }\n const payloads = await diviner.divine([payloadDivinerQuery])\n offset = (offset ?? 0) + payloads.length\n moreAvailable = payloads.length > 0\n console.log(`loadMapWithPayloadDiviner.offset: ${offset}`)\n console.log(`loadMapWithPayloadDiviner.moreAvailable: ${moreAvailable}`)\n const imagePayloadPairs = await Promise.all(\n payloads\n .filter((payload): payload is ImageThumbnail => payload.schema === ImageThumbnailSchema)\n .map<Promise<[string, ImageThumbnail]>>(async (payload) => [await PayloadHasher.hashAsync(payload), payload]),\n )\n imagePayloadPairs.forEach(([hash, payload]) => (newMap[payload.sourceUrl] = hash))\n }\n this._map = newMap\n }\n }\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n if (this._pollId) {\n clearTimeout(this._pollId)\n this._pollId = undefined\n }\n return await super.stopHandler()\n }\n\n private async attachArchivistEvents() {\n const archivist = await this.getArchivistInstance()\n const mapPromise = this.getSafeMap()\n archivist.on('inserted', async ({ payloads }) => {\n const map = await mapPromise\n const thumbnails = compact(payloads.filter((payload): payload is ImageThumbnail => payload.schema === ImageThumbnailSchema))\n await Promise.all(thumbnails.map(async (payload) => (map[payload.sourceUrl] = await PayloadHasher.hashAsync(payload))))\n })\n }\n\n private async getSafeMap() {\n let mapRetry = 100 //10 seconds max\n let map = this._map\n while (!map) {\n await delay(100)\n mapRetry = mapRetry - 1\n if (mapRetry === 0) {\n throw Error('Map Not Loaded')\n }\n map = this._map\n }\n return map\n }\n\n private async poll() {\n if (await this.started()) {\n const pollFrequency = this.pollFrequency\n if (pollFrequency) {\n this._pollId = setTimeout(async () => {\n this._pollId = undefined\n await this.loadMap()\n await this.poll()\n }, pollFrequency)\n } else {\n await this.loadMap()\n }\n }\n }\n}\n","import { ImageThumbnailSchema } from '@xyo-network/image-thumbnail-payload-plugin'\nimport { WitnessConfig } from '@xyo-network/witness'\n\nexport const ImageThumbnailWitnessConfigSchema = `${ImageThumbnailSchema}.witness.config` as const\nexport type ImageThumbnailWitnessConfigSchema = typeof ImageThumbnailWitnessConfigSchema\n\nexport type ImageThumbnailEncoding = 'PNG' | 'JPG' | 'GIF'\n\nexport type ImageThumbnailWitnessConfig = WitnessConfig<{\n encoding?: ImageThumbnailEncoding\n height?: number\n ipfsGateway?: string\n maxAsyncProcesses?: number\n maxCacheBytes?: number\n maxCacheEntries?: number\n quality?: number\n schema: ImageThumbnailWitnessConfigSchema\n width?: number\n}>\n","/* eslint-disable max-statements */\nimport { promises as dnsPromises } from 'node:dns'\n\nimport { compact } from '@xylabs/lodash'\nimport { URL } from '@xylabs/url'\nimport { axios, AxiosError, AxiosResponse } from '@xyo-network/axios'\nimport { PayloadHasher } from '@xyo-network/core'\nimport { ImageThumbnail, ImageThumbnailSchema } from '@xyo-network/image-thumbnail-payload-plugin'\nimport { UrlPayload, UrlSchema } from '@xyo-network/url-payload-plugin'\nimport { AbstractWitness } from '@xyo-network/witness'\nimport { Semaphore } from 'async-mutex'\nimport FileType from 'file-type'\nimport graphicsMagick from 'gm'\nimport hasbin from 'hasbin'\nimport { sha256 } from 'hash-wasm'\nimport { LRUCache } from 'lru-cache'\nimport shajs from 'sha.js'\nimport Url from 'url-parse'\n\nimport { ImageThumbnailEncoding, ImageThumbnailWitnessConfigSchema } from './Config'\nimport { getVideoFrameAsImageFluent } from './ffmpeg'\nimport { ImageThumbnailWitnessParams } from './Params'\n\n//TODO: Break this into two Witnesses?\n\n// setFfmpegPath(ffmpegPath)\n\n// eslint-disable-next-line import/no-named-as-default-member\nconst gm = graphicsMagick.subClass({ imageMagick: '7+' })\n\nexport interface ImageThumbnailWitnessError extends Error {\n name: 'ImageThumbnailWitnessError'\n url: string\n}\n\nexport interface DnsError extends Error {\n code: string\n}\n\nexport class ImageThumbnailWitness<TParams extends ImageThumbnailWitnessParams = ImageThumbnailWitnessParams> extends AbstractWitness<TParams> {\n static override configSchemas = [ImageThumbnailWitnessConfigSchema]\n\n private _cache?: LRUCache<string, ImageThumbnail>\n private _semaphore = new Semaphore(this.maxAsyncProcesses)\n\n get cache() {\n this._cache =\n this._cache ??\n new LRUCache<string, ImageThumbnail>({\n max: this.maxCacheEntries,\n maxSize: this.maxCacheBytes,\n //just returning the size of the data\n sizeCalculation: (value) => value.url?.length ?? 1,\n })\n return this._cache\n }\n\n get encoding() {\n return this.config.encoding ?? 'PNG'\n }\n\n get height() {\n return this.config.height ?? 128\n }\n\n get ipfGateway() {\n return this.config.ipfsGateway ?? '5d7b6582.beta.decentralnetworkservices.com'\n }\n\n get maxAsyncProcesses() {\n return this.config.maxAsyncProcesses ?? 2\n }\n\n get maxCacheBytes() {\n return this.config.maxCacheBytes ?? 1024 * 1024 * 16 //64MB max size\n }\n\n get maxCacheEntries() {\n return this.config.maxCacheEntries ?? 500\n }\n\n get quality() {\n return this.config.quality ?? 50\n }\n\n get width() {\n return this.config.width ?? 128\n }\n\n private static async binaryToSha256(data: Uint8Array) {\n await PayloadHasher.wasmInitialized\n if (PayloadHasher.wasmSupport.canUseWasm) {\n try {\n return await sha256(data)\n } catch (ex) {\n PayloadHasher.wasmSupport.allowWasm = false\n }\n }\n\n return shajs('sha256').update(data).digest().toString()\n }\n\n private static bufferFromDataUrl(url: string): Buffer | undefined {\n if (url.startsWith('data:image')) {\n const data = url.split(',')[1]\n if (data) {\n return Buffer.from(Uint8Array.from(atob(data), (c) => c.charCodeAt(0)))\n } else {\n const error: ImageThumbnailWitnessError = {\n message: 'Invalid data Url',\n name: 'ImageThumbnailWitnessError',\n url,\n }\n throw error\n }\n }\n }\n\n /**\n * Returns the equivalent IPFS gateway URL for the supplied URL.\n * @param urlToCheck The URL to check\n * @returns If the supplied URL is an IPFS URL, it converts the URL to the\n * equivalent IPFS gateway URL. Otherwise, returns the original URL.\n */\n checkIpfsUrl(urlToCheck: string) {\n const url = new URL(urlToCheck)\n let protocol = url.protocol\n let host = url.host\n let path = url.pathname\n const query = url.search\n if (protocol === 'ipfs:') {\n protocol = 'https:'\n host = this.ipfGateway\n path = url.host === 'ipfs' ? `ipfs${path}` : `ipfs/${url.host}${path}`\n const root = `${protocol}//${host}/${path}`\n return query?.length > 0 ? `${root}?${query}` : root\n } else {\n return urlToCheck\n }\n }\n\n protected override async observeHandler(payloads: UrlPayload[] = []): Promise<ImageThumbnail[]> {\n // eslint-disable-next-line import/no-named-as-default-member\n if (!hasbin.sync('magick')) {\n throw Error('ImageMagick is required for this witness')\n }\n const urlPayloads = payloads.filter((payload) => payload.schema === UrlSchema)\n return await this._semaphore.runExclusive(async () =>\n compact(\n await Promise.all(\n urlPayloads.map<Promise<ImageThumbnail>>(async ({ url }) => {\n const cachedResult = this.cache.get(url)\n if (cachedResult) {\n return cachedResult\n }\n let result: ImageThumbnail\n\n //if it is a data URL, return a Buffer\n const dataBuffer = ImageThumbnailWitness.bufferFromDataUrl(url)\n\n if (dataBuffer) {\n result = {\n schema: ImageThumbnailSchema,\n sourceHash: await ImageThumbnailWitness.binaryToSha256(dataBuffer),\n sourceUrl: url,\n url,\n }\n } else {\n //if it is ipfs, go through cloud flair\n const mutatedUrl = this.checkIpfsUrl(url)\n result = await this.fromHttp(mutatedUrl, url)\n }\n this.cache.set(url, result)\n return result\n }),\n ),\n ),\n )\n }\n\n private async createThumbnailDataUrl(sourceBuffer: Buffer, encoding?: ImageThumbnailEncoding) {\n const thumb = await new Promise<Buffer>((resolve, reject) => {\n gm(sourceBuffer)\n .quality(this.quality)\n .resize(this.width, this.height)\n .flatten()\n .toBuffer(encoding ?? this.encoding, (error, buffer) => {\n if (error) {\n reject(error)\n } else {\n resolve(buffer)\n }\n })\n })\n return `data:image/png;base64,${thumb.toString('base64')}`\n }\n\n /**\n * Creates an image thumbnail from a video.\n * @param videoBuffer The input video buffer.\n * @returns An buffer containing an image thumbnail for the video.\n */\n private async createThumbnailFromVideo(videoBuffer: Buffer) {\n const imageBuffer = await getVideoFrameAsImageFluent(videoBuffer)\n return this.createThumbnailDataUrl(imageBuffer)\n }\n\n private async fromHttp(url: string, sourceUrl?: string): Promise<ImageThumbnail> {\n let response: AxiosResponse\n let dnsResult: string[]\n try {\n const urlObj = new Url(url)\n dnsResult = await dnsPromises.resolve(urlObj.host)\n // console.log(`dnsResult: ${JSON.stringify(dnsResult, null, 2)}`)\n } catch (ex) {\n const error = ex as DnsError\n const result: ImageThumbnail = {\n http: {\n dnsError: error.code,\n },\n schema: ImageThumbnailSchema,\n sourceUrl: sourceUrl ?? url,\n }\n return result\n }\n try {\n response = await axios.get(url, {\n responseType: 'arraybuffer',\n })\n } catch (ex) {\n const axiosError = ex as AxiosError\n if (axiosError.isAxiosError) {\n //selectively pick fields from AxiosError\n const result: ImageThumbnail = {\n http: {\n ipAddress: dnsResult[0],\n status: axiosError?.response?.status,\n },\n schema: ImageThumbnailSchema,\n sourceUrl: sourceUrl ?? url,\n }\n return result\n } else {\n throw ex\n }\n }\n\n const result: ImageThumbnail = {\n http: {\n status: response.status,\n },\n schema: ImageThumbnailSchema,\n sourceUrl: sourceUrl ?? url,\n }\n\n if (response.status >= 200 && response.status < 300) {\n const contentType: string = response.headers['content-type']?.toString()\n const [mediaType, fileType] = contentType.split('/')\n result.mime = result.mime ?? {}\n result.mime.returned = mediaType\n const sourceBuffer = Buffer.from(response.data, 'binary')\n\n try {\n result.mime.detected = await FileType.fromBuffer(sourceBuffer)\n } catch (ex) {\n const error = ex as Error\n this.logger?.error(`FileType error: ${error.message}`)\n }\n\n const processImage = async (encoding?: ImageThumbnailEncoding) => {\n result.sourceHash = await ImageThumbnailWitness.binaryToSha256(sourceBuffer)\n result.url = await this.createThumbnailDataUrl(sourceBuffer, encoding)\n }\n\n const processVideo = async () => {\n // Gracefully handle the case where ffmpeg is not installed.\n // eslint-disable-next-line import/no-named-as-default-member\n if (hasbin.sync('ffmpeg')) {\n result.sourceHash = await ImageThumbnailWitness.binaryToSha256(sourceBuffer)\n result.url = await this.createThumbnailFromVideo(sourceBuffer)\n } else {\n result.mime = result.mime ?? {}\n result.mime.invalid = true\n }\n }\n\n let encoding: ImageThumbnailEncoding = 'PNG'\n\n switch (fileType.toUpperCase()) {\n case 'GIF':\n encoding = 'GIF'\n break\n case 'JPG':\n case 'JPEG':\n encoding = 'JPG'\n break\n }\n\n switch (mediaType) {\n case 'image': {\n await processImage(encoding)\n result.mime.type = mediaType\n break\n }\n case 'video': {\n await processVideo()\n result.mime.type = mediaType\n break\n }\n default: {\n switch (result.mime.detected?.mime) {\n case 'image': {\n await processImage()\n result.mime.type = result.mime.detected?.mime\n break\n }\n case 'video': {\n await processVideo()\n result.mime.type = result.mime.detected?.mime\n break\n }\n default: {\n result.mime.invalid = true\n break\n }\n }\n break\n }\n }\n }\n return result\n }\n}\n","import { uuid } from '@xyo-network/core'\nimport ffmpeg from 'fluent-ffmpeg'\nimport { unlink, writeFile } from 'fs/promises'\nimport { tmpdir } from 'os'\nimport { Writable, WritableOptions } from 'stream'\n\n/**\n * A Writable stream that collects output from ffmpeg.\n */\nclass FfmpegOutputStream extends Writable {\n private readonly chunks: Uint8Array[] = []\n\n constructor(options?: WritableOptions) {\n super(options)\n }\n\n override _write(chunk: never, _encoding: BufferEncoding, callback: (error?: Error | null) => void): void {\n this.chunks.push(chunk)\n callback()\n }\n\n /**\n * Collects the output from ffmpeg into a buffer.\n * @returns A buffer containing the concatenated\n * output from ffmpeg.\n */\n toBuffer = () => Buffer.concat(this.chunks)\n}\n\n/**\n * Execute FFmpeg using fluent API with provided input buffer and video thumbnail image.\n * @param videoBuffer Input video buffer.\n * @returns Output buffer containing the video thumbnail image.\n */\nexport const getVideoFrameAsImageFluent = async (videoBuffer: Buffer) => {\n // Get a temp file name\n const tmpFile = `/${tmpdir()}/${uuid()}`\n try {\n // Write videoBuffer to temp file for use as input to ffmpeg to\n // avoid issues with ffmpeg inferring premature EOF from buffer\n // passed via stdin (happens when ffmpeg is trying to infer\n // input video format)\n await writeFile(tmpFile, videoBuffer, { encoding: 'binary' })\n const imageBuffer = await new Promise<Buffer>((resolve, reject) => {\n // Create a Writable stream to collect PNG output from ffmpeg\n const ffmpegOutput = new FfmpegOutputStream()\n // Execute ffmpeg using fluent API\n ffmpeg()\n // NOTE: Uncomment to debug CLI args to ffmpeg\n // .on('start', (commandLine) => console.log('Spawned Ffmpeg with command: ' + commandLine))\n .on('error', (err) => reject(err.message))\n // Listen for the 'end' event to combine the output into a buffer holding the PNG image\n .on('end', () => resolve(ffmpegOutput.toBuffer()))\n .input(tmpFile) // Use temp file as input\n .takeFrames(1) // Only take 1st video frame\n .withNoAudio() // Don't include audio\n .outputOptions('-f image2pipe') // Write output to stdout\n .videoCodec('png') // Force PNG output\n // Start processing and direct ffmpeg stdout to writable stream\n .pipe(ffmpegOutput)\n })\n return imageBuffer\n } finally {\n // Cleanup temp file\n try {\n await unlink(tmpFile)\n } catch {\n // No error here since file doesn't exist\n }\n }\n}\n"],"mappings":"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","names":["import_image_thumbnail_payload_plugin","import_image_thumbnail_payload_plugin","module","import_image_thumbnail_payload_plugin","import_lodash","import_core","import_image_thumbnail_payload_plugin","import_core","ffmpeg","graphicsMagick","shajs","hasbin","Url","dnsPromises","result","FileType","encoding"]}