echogarden 0.11.12 → 0.11.13
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.
- package/data/schemas/options.json +16 -0
- package/dist/api/Alignment.js +2 -2
- package/dist/api/Alignment.js.map +1 -1
- package/dist/api/Recognition.js +2 -2
- package/dist/api/Recognition.js.map +1 -1
- package/dist/api/Synthesis.js +5 -4
- package/dist/api/Synthesis.js.map +1 -1
- package/dist/api/Translation.js +2 -2
- package/dist/api/Translation.js.map +1 -1
- package/dist/audio/AudioUtilities.d.ts +1 -0
- package/dist/audio/AudioUtilities.js +25 -7
- package/dist/audio/AudioUtilities.js.map +1 -1
- package/dist/cli/CLI.js +2 -2
- package/dist/cli/CLI.js.map +1 -1
- package/dist/recognition/WhisperSTT.js +2 -2
- package/dist/recognition/WhisperSTT.js.map +1 -1
- package/dist/subtitles/Subtitles.d.ts +10 -7
- package/dist/subtitles/Subtitles.js +268 -207
- package/dist/subtitles/Subtitles.js.map +1 -1
- package/docs/Options.md +4 -2
- package/package.json +7 -6
- package/src/alignment/DTWMfccSequenceAlignment.ts +43 -0
- package/src/alignment/DTWSequenceAlignment.ts +121 -0
- package/src/alignment/DTWSequenceAlignmentWindowed.ts +210 -0
- package/src/alignment/LevenshteinSequenceAlignment.ts +126 -0
- package/src/alignment/SpeechAlignment.ts +488 -0
- package/src/api/API.ts +12 -0
- package/src/api/APIOptions.ts +15 -0
- package/src/api/Alignment.ts +329 -0
- package/src/api/Common.ts +16 -0
- package/src/api/Denoising.ts +120 -0
- package/src/api/LanguageDetection.ts +286 -0
- package/src/api/Recognition.ts +344 -0
- package/src/api/Synthesis.ts +1735 -0
- package/src/api/Translation.ts +143 -0
- package/src/api/Vad.ts +172 -0
- package/src/audio/AudioBufferConversion.ts +248 -0
- package/src/audio/AudioPlayer.ts +358 -0
- package/src/audio/AudioRecorder.ts +91 -0
- package/src/audio/AudioUtilities.ts +392 -0
- package/src/audio/SoxPath.ts +24 -0
- package/src/cli/CLI.ts +1360 -0
- package/src/cli/CLIConfigFile.ts +91 -0
- package/src/cli/CLILauncher.ts +26 -0
- package/src/cli/CLIOptionsSchema.ts +54 -0
- package/src/cli/CLIParser.ts +41 -0
- package/src/cli/CLIStarter.ts +40 -0
- package/src/codecs/FFMpegTranscoder.ts +214 -0
- package/src/codecs/TIMITCodec.ts +17 -0
- package/src/codecs/WaveCodec.ts +260 -0
- package/src/denoising/RNNoise.ts +95 -0
- package/src/dsp/BiquadFilter.ts +488 -0
- package/src/dsp/FFT.ts +187 -0
- package/src/dsp/MFCC.ts +227 -0
- package/src/dsp/MelSpectogram.ts +145 -0
- package/src/dsp/Rubberband.ts +249 -0
- package/src/dsp/Sonic.ts +59 -0
- package/src/dsp/SpeexResampler.ts +79 -0
- package/src/math/VectorMath.ts +812 -0
- package/src/nlp/ChineseSegmentation.ts +68 -0
- package/src/nlp/CompromiseNLP.ts +113 -0
- package/src/nlp/EspeakPhonemizer.ts +168 -0
- package/src/nlp/IPA.ts +139 -0
- package/src/nlp/JapaneseSegmentation.ts +53 -0
- package/src/nlp/Lexicon.ts +119 -0
- package/src/nlp/PhoneConversion.ts +508 -0
- package/src/nlp/Segmentation.ts +237 -0
- package/src/nlp/TextNormalizer.ts +160 -0
- package/src/recognition/AmazonTranscribeSTT.ts +112 -0
- package/src/recognition/AzureCognitiveServicesSTT.ts +76 -0
- package/src/recognition/GoogleCloudSTT.ts +92 -0
- package/src/recognition/SileroSTT.ts +173 -0
- package/src/recognition/VoskSTT.ts +112 -0
- package/src/recognition/WhisperSTT.ts +1518 -0
- package/src/server/Client.ts +297 -0
- package/src/server/Server.ts +178 -0
- package/src/server/ServerStarter.ts +12 -0
- package/src/server/Worker.ts +400 -0
- package/src/server/WorkerStarter.ts +38 -0
- package/src/speech-language-detection/SileroLanguageDetection.ts +105 -0
- package/src/subtitles/Subtitles.ts +478 -0
- package/src/synthesis/AwsPollyTTS.ts +78 -0
- package/src/synthesis/AzureCognitiveServicesTTS.ts +146 -0
- package/src/synthesis/CoquiServerTTS.ts +29 -0
- package/src/synthesis/ElevenLabsTTS.ts +104 -0
- package/src/synthesis/EspeakTTS.ts +552 -0
- package/src/synthesis/FliteTTS.ts +387 -0
- package/src/synthesis/GoogleCloudTTS.ts +112 -0
- package/src/synthesis/GoogleTranslateTTS.ts +210 -0
- package/src/synthesis/MicrosoftEdgeTTS.ts +298 -0
- package/src/synthesis/SamTTS.ts +30 -0
- package/src/synthesis/SapiTTS.ts +222 -0
- package/src/synthesis/StreamlabsPollyTTS.ts +114 -0
- package/src/synthesis/SvoxPicoTTS.ts +318 -0
- package/src/synthesis/VitsTTS.ts +734 -0
- package/src/tests/Test.ts +24 -0
- package/src/text-language-detection/FastTextLanguageDetection.ts +53 -0
- package/src/text-language-detection/TinyLDLanguageDetection.ts +16 -0
- package/src/typings/Fillers.d.ts +41 -0
- package/src/utilities/BinaryArrayConversion.ts +159 -0
- package/src/utilities/Compression.ts +91 -0
- package/src/utilities/FileDownloader.ts +201 -0
- package/src/utilities/FileSystem.ts +265 -0
- package/src/utilities/Hashing.ts +230 -0
- package/src/utilities/Locale.ts +119 -0
- package/src/utilities/Logger.ts +72 -0
- package/src/utilities/NdArrayUtilities.ts +31 -0
- package/src/utilities/ObjectUtilities.ts +169 -0
- package/src/utilities/OpenPromise.ts +13 -0
- package/src/utilities/PackageManager.ts +97 -0
- package/src/utilities/Queue.ts +17 -0
- package/src/utilities/RandomGenerator.ts +237 -0
- package/src/utilities/SignalChannel.ts +22 -0
- package/src/utilities/TarballMaker.ts +68 -0
- package/src/utilities/Timeline.ts +231 -0
- package/src/utilities/Timer.ts +93 -0
- package/src/utilities/Utilities.ts +574 -0
- package/src/utilities/WasmMemoryManager.ts +516 -0
- package/src/utilities/WebReader.ts +55 -0
- package/src/utilities/WikipediaReader.ts +41 -0
- package/src/voice-activity-detection/SileroVAD.ts +86 -0
- package/src/voice-activity-detection/WebRtcVAD.ts +76 -0
|
@@ -0,0 +1,574 @@
|
|
|
1
|
+
import * as readline from 'node:readline'
|
|
2
|
+
import { IncomingMessage } from 'node:http'
|
|
3
|
+
import { inspect } from 'node:util'
|
|
4
|
+
|
|
5
|
+
import { RandomGenerator } from './RandomGenerator.js'
|
|
6
|
+
import { randomUUID, randomBytes } from 'node:crypto'
|
|
7
|
+
|
|
8
|
+
const log = logToStderr
|
|
9
|
+
|
|
10
|
+
export function concatFloat32Arrays(arrays: Float32Array[]) {
|
|
11
|
+
return concatTypedArrays<Float32Array>(Float32Array, arrays)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function concatTypedArrays<R>(ArrayConstructor: any, arrays: any[]) {
|
|
15
|
+
let totalLength = 0
|
|
16
|
+
|
|
17
|
+
for (const arr of arrays) {
|
|
18
|
+
totalLength += arr.length
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const result = new ArrayConstructor(totalLength)
|
|
22
|
+
|
|
23
|
+
let offset = 0
|
|
24
|
+
|
|
25
|
+
for (const arr of arrays) {
|
|
26
|
+
result.set(arr, offset)
|
|
27
|
+
offset += arr.length
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return <R>result
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function shuffleArray<T>(array: T[], randomGen: RandomGenerator) {
|
|
34
|
+
return shuffleArrayInPlace(array.slice(), randomGen)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function shuffleArrayInPlace<T>(array: T[], randomGen: RandomGenerator) {
|
|
38
|
+
const vectorCount = array.length
|
|
39
|
+
|
|
40
|
+
for (let i = 0; i < vectorCount - 1; i++) {
|
|
41
|
+
const value = array[i]
|
|
42
|
+
const targetIndex = randomGen.getIntInRange(i + 1, vectorCount)
|
|
43
|
+
|
|
44
|
+
array[i] = array[targetIndex]
|
|
45
|
+
array[targetIndex] = value
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return array
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function simplifyPunctuationCharacters(text: string) {
|
|
52
|
+
return text
|
|
53
|
+
.replaceAll(`“`, `"`)
|
|
54
|
+
.replaceAll(`”`, `"`)
|
|
55
|
+
.replaceAll(`„`, `"`)
|
|
56
|
+
.replaceAll(`ߵ`, `"`)
|
|
57
|
+
.replaceAll(`ߴ`, `"`)
|
|
58
|
+
.replaceAll(`«`, `"`)
|
|
59
|
+
.replaceAll(`»`, `"`)
|
|
60
|
+
|
|
61
|
+
.replaceAll(`’`, `'`)
|
|
62
|
+
.replaceAll(`ʼ`, `'`)
|
|
63
|
+
.replaceAll(`ʼ`, `'`)
|
|
64
|
+
.replaceAll(`'`, `'`)
|
|
65
|
+
.replaceAll(`,`, `,`)
|
|
66
|
+
.replaceAll(`、`, `,`)
|
|
67
|
+
.replaceAll(`:`, `:`)
|
|
68
|
+
.replaceAll(`;`, `;`)
|
|
69
|
+
.replaceAll(`。`, `.`)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function writeToStderr(message: any) {
|
|
73
|
+
process.stderr.write(message)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function printToStderr(message: any) {
|
|
77
|
+
if (typeof message == 'string') {
|
|
78
|
+
writeToStderr(message)
|
|
79
|
+
} else {
|
|
80
|
+
writeToStderr(objToString(message))
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function logToStderr(message: any) {
|
|
85
|
+
printToStderr(message)
|
|
86
|
+
writeToStderr("\n")
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function objToString(obj: any) {
|
|
90
|
+
const formattedString = inspect(obj, {
|
|
91
|
+
showHidden: false,
|
|
92
|
+
depth: null,
|
|
93
|
+
colors: false,
|
|
94
|
+
maxArrayLength: null,
|
|
95
|
+
maxStringLength: null,
|
|
96
|
+
compact: 5,
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
return formattedString
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function getRandomHexString(charCount = 32, upperCase = false) {
|
|
103
|
+
if (charCount % 2 !== 0) {
|
|
104
|
+
throw new Error(`'charCount' must be an even number`)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
let hex = randomBytes(charCount / 2).toString("hex")
|
|
108
|
+
|
|
109
|
+
if (upperCase) {
|
|
110
|
+
hex = hex.toUpperCase()
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return hex
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function getRandomUUID(dashes = true) {
|
|
117
|
+
let uuid = randomUUID() as string
|
|
118
|
+
|
|
119
|
+
if (dashes == false) {
|
|
120
|
+
uuid = uuid.replaceAll("-", "")
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return uuid
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function sumArray<T>(arr: Array<T>, valueGetter: (item: T) => number) {
|
|
127
|
+
let sum = 0
|
|
128
|
+
|
|
129
|
+
for (let i = 0; i < arr.length; i++) {
|
|
130
|
+
sum += valueGetter(arr[i])
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return sum
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function includesAnyOf(str: string, substrings: string[]) {
|
|
137
|
+
return indexOfAnyOf(str, substrings) >= 0
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function indexOfAnyOf(str: string, substrings: string[]) {
|
|
141
|
+
for (const substring of substrings) {
|
|
142
|
+
const index = str.indexOf(substring)
|
|
143
|
+
|
|
144
|
+
if (index >= 0) {
|
|
145
|
+
return index
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return -1
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function startsWithAnyOf(str: string, prefixes: string[]) {
|
|
153
|
+
for (const prefix of prefixes) {
|
|
154
|
+
if (str.startsWith(prefix)) {
|
|
155
|
+
return true
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return false
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function roundToDigits(val: number, digits = 3) {
|
|
163
|
+
const multiplier = 10 ** digits
|
|
164
|
+
return Math.round(val * multiplier) / multiplier
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function delay(timeMs: number) {
|
|
168
|
+
return new Promise((resolve) => {
|
|
169
|
+
setTimeout(resolve, timeMs)
|
|
170
|
+
})
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function yieldToEventLoop() {
|
|
174
|
+
return new Promise((resolve) => {
|
|
175
|
+
setImmediate(resolve)
|
|
176
|
+
})
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function printMatrix(matrix: Float32Array[]) {
|
|
180
|
+
const rowCount = matrix.length
|
|
181
|
+
|
|
182
|
+
for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
|
|
183
|
+
log(matrix[rowIndex].join(", "))
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export function stringifyAndFormatJson(obj: any) {
|
|
188
|
+
return JSON.stringify(obj, undefined, 4)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function secondsToHMS(totalSeconds: number) {
|
|
192
|
+
let remainingSeconds = totalSeconds
|
|
193
|
+
|
|
194
|
+
const hours = Math.floor(remainingSeconds / 60 / 60)
|
|
195
|
+
remainingSeconds -= hours * 60 * 60
|
|
196
|
+
|
|
197
|
+
const minutes = Math.floor(remainingSeconds / 60)
|
|
198
|
+
remainingSeconds -= minutes * 60
|
|
199
|
+
|
|
200
|
+
const seconds = Math.floor(remainingSeconds)
|
|
201
|
+
remainingSeconds -= seconds
|
|
202
|
+
|
|
203
|
+
const milliseconds = Math.floor(remainingSeconds * 1000)
|
|
204
|
+
|
|
205
|
+
return { hours, minutes, seconds, milliseconds }
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export function secondsToMS(totalSeconds: number) {
|
|
209
|
+
const { hours, minutes, seconds, milliseconds } = secondsToHMS(totalSeconds)
|
|
210
|
+
|
|
211
|
+
return { minutes: (hours * 60) + minutes, seconds, milliseconds }
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export function formatHMS(timeHMS: { hours: number, minutes: number, seconds: number, milliseconds: number }, decimalSeparator = ".") {
|
|
215
|
+
return `${formatIntegerWithLeadingZeros(timeHMS.hours, 2)}:${formatIntegerWithLeadingZeros(timeHMS.minutes, 2)}:${formatIntegerWithLeadingZeros(timeHMS.seconds, 2)}${decimalSeparator}${formatIntegerWithLeadingZeros(timeHMS.milliseconds, 3)}`
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export function formatMS(timeMS: { minutes: number, seconds: number, milliseconds: number }, decimalSeparator = ".") {
|
|
219
|
+
return `${formatIntegerWithLeadingZeros(timeMS.minutes, 2)}:${formatIntegerWithLeadingZeros(timeMS.seconds, 2)}${decimalSeparator}${formatIntegerWithLeadingZeros(timeMS.milliseconds, 3)}`
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export function formatIntegerWithLeadingZeros(num: number, minDigitCount: number) {
|
|
223
|
+
num = Math.floor(num)
|
|
224
|
+
|
|
225
|
+
let numAsString = `${num}`
|
|
226
|
+
|
|
227
|
+
while (numAsString.length < minDigitCount) {
|
|
228
|
+
numAsString = `0${numAsString}`
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return numAsString
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export function intsInRange(start: number, end: number) {
|
|
235
|
+
const result: number[] = []
|
|
236
|
+
|
|
237
|
+
for (let i = start; i < end; i++) {
|
|
238
|
+
result.push(i)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return result
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export function randomIntsInRange(count: number, min: number, max: number) {
|
|
245
|
+
const randomArray: number[] = []
|
|
246
|
+
|
|
247
|
+
for (let i = 0; i < count; i++) {
|
|
248
|
+
randomArray.push(randomIntInRange(min, max))
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return randomArray
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export function randomIntInRange(min: number, max: number) {
|
|
255
|
+
return Math.floor(randomFloatInRange(min, max))
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export function randomFloatsInRange(count: number, min = 0.0, max = 1.0) {
|
|
259
|
+
const randomVector: number[] = []
|
|
260
|
+
|
|
261
|
+
for (let i = 0; i < count; i++) {
|
|
262
|
+
randomVector.push(randomFloatInRange(min, max))
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return randomVector
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export function randomFloatInRange(min: number, max: number) {
|
|
269
|
+
return min + Math.random() * (max - min)
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export function serializeMapToObject<V>(map: Map<string, V>) {
|
|
273
|
+
const obj: { [key: string]: V } = {}
|
|
274
|
+
|
|
275
|
+
for (const [key, value] of map) {
|
|
276
|
+
obj[key] = value
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return obj
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export function deserializeObjectToMap<V>(obj: { [key: string]: V }) {
|
|
283
|
+
const map = new Map<string, V>()
|
|
284
|
+
|
|
285
|
+
for (const key in obj) {
|
|
286
|
+
map.set(key, obj[key])
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return map
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
export function waitTimeout(timeout = 0) {
|
|
293
|
+
return new Promise<void>((resolve) => setTimeout(() => {
|
|
294
|
+
resolve()
|
|
295
|
+
}, timeout))
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export function waitImmediate() {
|
|
299
|
+
return new Promise<void>((resolve) => setImmediate(() => {
|
|
300
|
+
resolve()
|
|
301
|
+
}))
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export function waitNextTick() {
|
|
305
|
+
return new Promise<void>((resolve) => process.nextTick(() => resolve()))
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export function setupUnhandledExceptionListeners() {
|
|
309
|
+
process.on('unhandledRejection', (e: any) => {
|
|
310
|
+
log(`Unhandled promise rejection:\n ${e}`)
|
|
311
|
+
process.exit(1)
|
|
312
|
+
})
|
|
313
|
+
|
|
314
|
+
process.on('uncaughtException', function (e) {
|
|
315
|
+
log(`Uncaught exception:\n ${e}`)
|
|
316
|
+
process.exit(1)
|
|
317
|
+
})
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export function setupProgramTerminationListeners(cleanupFunc?: () => void) {
|
|
321
|
+
function exitProcess(exitCode = 0) {
|
|
322
|
+
if (cleanupFunc) {
|
|
323
|
+
cleanupFunc()
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
process.exit(exitCode)
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
process.on('SIGINT', () => exitProcess(0))
|
|
330
|
+
process.on('SIGQUIT', () => exitProcess(0))
|
|
331
|
+
process.on('SIGTERM', () => exitProcess(0))
|
|
332
|
+
|
|
333
|
+
if (process.stdin.isTTY) {
|
|
334
|
+
readline.emitKeypressEvents(process.stdin)
|
|
335
|
+
|
|
336
|
+
process.stdin.setRawMode(true)
|
|
337
|
+
|
|
338
|
+
process.stdin.on('keypress', (str, key) => {
|
|
339
|
+
if (key.name == 'escape') {
|
|
340
|
+
exitProcess(0)
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (key.ctrl == true && key.name == 'c') {
|
|
344
|
+
exitProcess(0)
|
|
345
|
+
}
|
|
346
|
+
})
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
export function clip(num: number, min: number, max: number) {
|
|
351
|
+
return Math.max(min, Math.min(max, num))
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
export function readBinaryIncomingMessage(incomingMessage: IncomingMessage) {
|
|
355
|
+
return new Promise<Buffer>((resolve, reject) => {
|
|
356
|
+
const chunks: Buffer[] = []
|
|
357
|
+
|
|
358
|
+
incomingMessage.on("data", (chunk) => {
|
|
359
|
+
chunks.push(Buffer.from(chunk))
|
|
360
|
+
})
|
|
361
|
+
|
|
362
|
+
incomingMessage.on("end", () => {
|
|
363
|
+
resolve(Buffer.concat(chunks))
|
|
364
|
+
})
|
|
365
|
+
|
|
366
|
+
incomingMessage.on("error", (e) => {
|
|
367
|
+
reject(e)
|
|
368
|
+
})
|
|
369
|
+
})
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
export function splitFloat32Array(nums: Float32Array, partSize: number): Float32Array[] {
|
|
373
|
+
const result: Float32Array[] = []
|
|
374
|
+
|
|
375
|
+
for (let offset = 0; offset < nums.length; offset += partSize) {
|
|
376
|
+
result.push(nums.subarray(offset, offset + partSize))
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
return result
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
export async function sha256AsHex(input: string) {
|
|
383
|
+
const crypto = await import('crypto')
|
|
384
|
+
const hash = crypto.createHash('sha256').update(input).digest('hex')
|
|
385
|
+
|
|
386
|
+
return hash
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
export async function commandExists(command: string) {
|
|
390
|
+
const { default: commandExists } = await import("command-exists")
|
|
391
|
+
|
|
392
|
+
try {
|
|
393
|
+
await commandExists(command)
|
|
394
|
+
return true
|
|
395
|
+
} catch {
|
|
396
|
+
return false
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
export async function convertHtmlToText(html: string) {
|
|
401
|
+
const { convert } = await import('html-to-text')
|
|
402
|
+
|
|
403
|
+
const text = convert(html, {
|
|
404
|
+
wordwrap: null,
|
|
405
|
+
|
|
406
|
+
selectors: [
|
|
407
|
+
{ selector: 'a', options: { ignoreHref: true } },
|
|
408
|
+
{ selector: 'img', format: 'skip' },
|
|
409
|
+
{ selector: 'h1', options: { uppercase: false } },
|
|
410
|
+
{ selector: 'h2', options: { uppercase: false } },
|
|
411
|
+
{ selector: 'h3', options: { uppercase: false } },
|
|
412
|
+
{ selector: 'h4', options: { uppercase: false } },
|
|
413
|
+
{ selector: 'table', options: { uppercaseHeaderCells: false } }
|
|
414
|
+
]
|
|
415
|
+
})
|
|
416
|
+
|
|
417
|
+
return text || ""
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
export function formatListWithQuotedElements(strings: string[], quoteSymbol = `'`) {
|
|
421
|
+
return strings.map(str => `${quoteSymbol}${str}${quoteSymbol}`).join(", ")
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
export async function resolveModuleMainPath(moduleName: string) {
|
|
425
|
+
const { resolve } = await import('import-meta-resolve')
|
|
426
|
+
const { fileURLToPath } = await import('url')
|
|
427
|
+
|
|
428
|
+
return fileURLToPath(await resolve(moduleName, import.meta.url))
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
export function getWithDefault<T>(value: T | undefined, defaultValue: T) {
|
|
432
|
+
if (value === undefined) {
|
|
433
|
+
return defaultValue
|
|
434
|
+
} else {
|
|
435
|
+
return value
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
export function splitFilenameOnExtendedExtension(filenameWithExtension: string) {
|
|
440
|
+
let splitPoint = filenameWithExtension.length
|
|
441
|
+
|
|
442
|
+
for (let i = filenameWithExtension.length - 1; i >= 0; i--) {
|
|
443
|
+
if (filenameWithExtension[i] == ".") {
|
|
444
|
+
if (/^[a-zA-Z0-9\.]+$/.test(filenameWithExtension.slice(i + 1))) {
|
|
445
|
+
splitPoint = i
|
|
446
|
+
|
|
447
|
+
continue
|
|
448
|
+
} else {
|
|
449
|
+
break
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
const name = filenameWithExtension.slice(0, splitPoint)
|
|
455
|
+
const ext = filenameWithExtension.slice(splitPoint + 1)
|
|
456
|
+
|
|
457
|
+
return [name, ext]
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
export function getUTF32Chars(str: string) {
|
|
461
|
+
const utf32chars: string[] = []
|
|
462
|
+
const mapping: number[] = []
|
|
463
|
+
|
|
464
|
+
let utf32Index = 0
|
|
465
|
+
|
|
466
|
+
for (const utf32char of str) {
|
|
467
|
+
utf32chars.push(utf32char)
|
|
468
|
+
|
|
469
|
+
for (let i = 0; i < utf32char.length; i++) {
|
|
470
|
+
mapping.push(utf32Index)
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
utf32Index += 1
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
mapping.push(utf32Index)
|
|
477
|
+
|
|
478
|
+
return { utf32chars, mapping }
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
export function getRepetitionScoreRelativeToFirstSubstring(tokens: string[] | number[]) {
|
|
482
|
+
const maxOrder = Math.floor(tokens.length)
|
|
483
|
+
|
|
484
|
+
const matchCountForOrder: number[] = []
|
|
485
|
+
|
|
486
|
+
for (let i = 0; i <= maxOrder; i++) {
|
|
487
|
+
matchCountForOrder.push(0)
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
for (let offset = 0; offset < tokens.length; offset++) {
|
|
491
|
+
for (let order = 1; order <= maxOrder; order++) {
|
|
492
|
+
const referenceToken = tokens[-1 + order]
|
|
493
|
+
const targetToken = tokens[offset + order]
|
|
494
|
+
|
|
495
|
+
if (targetToken == referenceToken) {
|
|
496
|
+
matchCountForOrder[order] += 1
|
|
497
|
+
} else {
|
|
498
|
+
break
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
const scores = matchCountForOrder.map((count, index) => count * index)
|
|
504
|
+
|
|
505
|
+
let maxScoreOrder = -1
|
|
506
|
+
let maxScore = -Infinity
|
|
507
|
+
|
|
508
|
+
for (let i = 1; i <= matchCountForOrder.length; i++) {
|
|
509
|
+
const score = scores[i]
|
|
510
|
+
|
|
511
|
+
if (score > maxScore) {
|
|
512
|
+
maxScoreOrder = i
|
|
513
|
+
maxScore = score
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
return { maxScore, maxScoreOrder }
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
export function getConsecutiveRepetitionScoreRelativeToFirstSubstring(tokens: string[] | number[]) {
|
|
521
|
+
function countRepetitionForLength(len: number) {
|
|
522
|
+
let count = 0
|
|
523
|
+
|
|
524
|
+
for (let offset = len; offset < tokens.length; offset += len) {
|
|
525
|
+
for (let i = 0; i < len; i++) {
|
|
526
|
+
if (tokens[i] != tokens[offset + i]) {
|
|
527
|
+
return count
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
count += 1
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
return count
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
const maxLength = Math.floor(tokens.length / 2)
|
|
538
|
+
|
|
539
|
+
const repeatCountForLength: number[] = []
|
|
540
|
+
|
|
541
|
+
for (let i = 0; i <= maxLength; i++) {
|
|
542
|
+
repeatCountForLength.push(0)
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
for (let targetLen = 1; targetLen <= maxLength; targetLen++) {
|
|
546
|
+
repeatCountForLength[targetLen] = countRepetitionForLength(targetLen)
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
const scores = repeatCountForLength.map((count, index) => count * index)
|
|
550
|
+
|
|
551
|
+
let maxScoreLength = -1
|
|
552
|
+
let maxScore = -Infinity
|
|
553
|
+
|
|
554
|
+
for (let i = 1; i <= repeatCountForLength.length; i++) {
|
|
555
|
+
const score = scores[i]
|
|
556
|
+
|
|
557
|
+
if (score > maxScore) {
|
|
558
|
+
maxScoreLength = i
|
|
559
|
+
maxScore = score
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
return { maxScore, maxScoreLength, repeatCountForLength }
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
export async function resolveModuleScriptPath(moduleName: string) {
|
|
567
|
+
const { resolve } = await import('import-meta-resolve')
|
|
568
|
+
|
|
569
|
+
const scriptPath = await resolve(moduleName, import.meta.url)
|
|
570
|
+
|
|
571
|
+
const { fileURLToPath } = await import('url')
|
|
572
|
+
|
|
573
|
+
return fileURLToPath(scriptPath)
|
|
574
|
+
}
|