echogarden 1.8.7 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (299) hide show
  1. package/README.md +23 -18
  2. package/data/schemas/options.json +52 -47
  3. package/dist/alignment/DTWSequenceAlignment.d.ts +1 -1
  4. package/dist/alignment/DTWSequenceAlignment.js +5 -5
  5. package/dist/alignment/DTWSequenceAlignment.js.map +1 -1
  6. package/dist/alignment/SpeechAlignment.js +6 -6
  7. package/dist/alignment/SpeechAlignment.js.map +1 -1
  8. package/dist/api/Alignment.d.ts +1 -1
  9. package/dist/api/Alignment.js +49 -11
  10. package/dist/api/Alignment.js.map +1 -1
  11. package/dist/api/Denoising.d.ts +4 -2
  12. package/dist/api/Denoising.js +65 -13
  13. package/dist/api/Denoising.js.map +1 -1
  14. package/dist/api/SourceSeparation.js +9 -6
  15. package/dist/api/SourceSeparation.js.map +1 -1
  16. package/dist/api/SpeechLanguageDetection.js +4 -4
  17. package/dist/api/SpeechLanguageDetection.js.map +1 -1
  18. package/dist/api/Synthesis.d.ts +2 -2
  19. package/dist/api/Synthesis.js +10 -7
  20. package/dist/api/Synthesis.js.map +1 -1
  21. package/dist/api/VoiceActivityDetection.js +2 -2
  22. package/dist/api/VoiceActivityDetection.js.map +1 -1
  23. package/dist/audio/AudioBufferConversion.d.ts +2 -2
  24. package/dist/audio/AudioBufferConversion.js +77 -43
  25. package/dist/audio/AudioBufferConversion.js.map +1 -1
  26. package/dist/audio/AudioPlayer.d.ts +7 -5
  27. package/dist/audio/AudioPlayer.js +135 -49
  28. package/dist/audio/AudioPlayer.js.map +1 -1
  29. package/dist/audio/AudioUtilities.d.ts +4 -3
  30. package/dist/audio/AudioUtilities.js +30 -15
  31. package/dist/audio/AudioUtilities.js.map +1 -1
  32. package/dist/audio/SoxPath.js +3 -3
  33. package/dist/audio/SoxPath.js.map +1 -1
  34. package/dist/build-tools/MakeTarballsForInstalledPackages.js +3 -3
  35. package/dist/build-tools/MakeTarballsForInstalledPackages.js.map +1 -1
  36. package/dist/cli/CLI.js +30 -36
  37. package/dist/cli/CLI.js.map +1 -1
  38. package/dist/cli/CLIConfigFile.js +2 -2
  39. package/dist/cli/CLIConfigFile.js.map +1 -1
  40. package/dist/cli/CLIOptions.d.ts +2 -0
  41. package/dist/cli/CLIOptions.js +1 -1
  42. package/dist/cli/CLIOptions.js.map +1 -1
  43. package/dist/codecs/FFMpegTranscoder.d.ts +3 -3
  44. package/dist/codecs/FFMpegTranscoder.js +6 -6
  45. package/dist/codecs/FFMpegTranscoder.js.map +1 -1
  46. package/dist/codecs/TIMITCodec.d.ts +1 -1
  47. package/dist/codecs/TIMITCodec.js +4 -3
  48. package/dist/codecs/TIMITCodec.js.map +1 -1
  49. package/dist/codecs/WaveCodec.d.ts +3 -3
  50. package/dist/codecs/WaveCodec.js +37 -34
  51. package/dist/codecs/WaveCodec.js.map +1 -1
  52. package/dist/data-structures/DynamicTypedArray.d.ts +17 -0
  53. package/dist/data-structures/DynamicTypedArray.js +47 -0
  54. package/dist/data-structures/DynamicTypedArray.js.map +1 -0
  55. package/dist/data-structures/Queue.js.map +1 -0
  56. package/dist/data-structures/WindowedList.js.map +1 -0
  57. package/dist/denoising/NSNet2.d.ts +26 -0
  58. package/dist/denoising/NSNet2.js +128 -0
  59. package/dist/denoising/NSNet2.js.map +1 -0
  60. package/dist/denoising/RNNoise.js +3 -3
  61. package/dist/denoising/RNNoise.js.map +1 -1
  62. package/dist/dsp/FFT.d.ts +6 -1
  63. package/dist/dsp/FFT.js +17 -0
  64. package/dist/dsp/FFT.js.map +1 -1
  65. package/dist/encodings/Ascii.d.ts +10 -0
  66. package/dist/encodings/Ascii.js +41 -0
  67. package/dist/encodings/Ascii.js.map +1 -0
  68. package/dist/encodings/Base64.d.ts +5 -0
  69. package/dist/encodings/Base64.js +114 -0
  70. package/dist/encodings/Base64.js.map +1 -0
  71. package/dist/encodings/Hex.d.ts +3 -0
  72. package/dist/encodings/Hex.js +52 -0
  73. package/dist/encodings/Hex.js.map +1 -0
  74. package/dist/{utilities → encodings}/LEB128.d.ts +1 -1
  75. package/dist/{utilities → encodings}/LEB128.js +4 -4
  76. package/dist/encodings/LEB128.js.map +1 -0
  77. package/dist/{utilities → encodings}/LPVarInt.d.ts +1 -1
  78. package/dist/{utilities → encodings}/LPVarInt.js +6 -6
  79. package/dist/encodings/LPVarInt.js.map +1 -0
  80. package/dist/encodings/TextEncodingsCommon.d.ts +4 -0
  81. package/dist/encodings/TextEncodingsCommon.js +2 -0
  82. package/dist/encodings/TextEncodingsCommon.js.map +1 -0
  83. package/dist/encodings/Utf16.d.ts +10 -0
  84. package/dist/encodings/Utf16.js +36 -0
  85. package/dist/encodings/Utf16.js.map +1 -0
  86. package/dist/encodings/Utf32.d.ts +9 -0
  87. package/dist/encodings/Utf32.js +44 -0
  88. package/dist/encodings/Utf32.js.map +1 -0
  89. package/dist/encodings/Utf8.d.ts +10 -0
  90. package/dist/encodings/Utf8.js +97 -0
  91. package/dist/encodings/Utf8.js.map +1 -0
  92. package/dist/math/MedianFilter.js.map +1 -1
  93. package/dist/nlp/JapaneseSegmentation.js +2 -2
  94. package/dist/nlp/JapaneseSegmentation.js.map +1 -1
  95. package/dist/recognition/GoogleCloudSTT.js +2 -1
  96. package/dist/recognition/GoogleCloudSTT.js.map +1 -1
  97. package/dist/recognition/SileroSTT.js +3 -3
  98. package/dist/recognition/SileroSTT.js.map +1 -1
  99. package/dist/recognition/VoskSTT.js +3 -3
  100. package/dist/recognition/VoskSTT.js.map +1 -1
  101. package/dist/recognition/WhisperCppSTT.js +4 -5
  102. package/dist/recognition/WhisperCppSTT.js.map +1 -1
  103. package/dist/recognition/WhisperSTT.js +8 -7
  104. package/dist/recognition/WhisperSTT.js.map +1 -1
  105. package/dist/server/Client.d.ts +1 -1
  106. package/dist/server/Client.js +2 -1
  107. package/dist/server/Client.js.map +1 -1
  108. package/dist/server/Server.js +5 -4
  109. package/dist/server/Server.js.map +1 -1
  110. package/dist/server/Worker.js +1 -1
  111. package/dist/server/Worker.js.map +1 -1
  112. package/dist/source-separation/MDXNetSourceSeparation.js +1 -1
  113. package/dist/source-separation/MDXNetSourceSeparation.js.map +1 -1
  114. package/dist/speech-search/DTWSpeechSearch.d.ts +1 -1
  115. package/dist/speech-search/DTWSpeechSearch.js +25 -6
  116. package/dist/speech-search/DTWSpeechSearch.js.map +1 -1
  117. package/dist/subtitles/Subtitles.js +2 -2
  118. package/dist/subtitles/Subtitles.js.map +1 -1
  119. package/dist/synthesis/AzureCognitiveServicesTTS.js +17 -18
  120. package/dist/synthesis/AzureCognitiveServicesTTS.js.map +1 -1
  121. package/dist/synthesis/CoquiServerTTS.js +1 -1
  122. package/dist/synthesis/CoquiServerTTS.js.map +1 -1
  123. package/dist/synthesis/ElevenlabsTTS.js +1 -1
  124. package/dist/synthesis/ElevenlabsTTS.js.map +1 -1
  125. package/dist/synthesis/EspeakTTS.d.ts +0 -1
  126. package/dist/synthesis/EspeakTTS.js +0 -9
  127. package/dist/synthesis/EspeakTTS.js.map +1 -1
  128. package/dist/synthesis/FliteTTS.js +7 -8
  129. package/dist/synthesis/FliteTTS.js.map +1 -1
  130. package/dist/synthesis/GoogleCloudTTS.d.ts +1 -1
  131. package/dist/synthesis/GoogleCloudTTS.js +2 -1
  132. package/dist/synthesis/GoogleCloudTTS.js.map +1 -1
  133. package/dist/synthesis/GoogleTranslateTTS.d.ts +1 -1
  134. package/dist/synthesis/GoogleTranslateTTS.js +4 -3
  135. package/dist/synthesis/GoogleTranslateTTS.js.map +1 -1
  136. package/dist/synthesis/MicrosoftEdgeTTS.js +32 -7
  137. package/dist/synthesis/MicrosoftEdgeTTS.js.map +1 -1
  138. package/dist/synthesis/SapiTTS.js +1 -1
  139. package/dist/synthesis/SapiTTS.js.map +1 -1
  140. package/dist/synthesis/StreamlabsPollyTTS.d.ts +1 -1
  141. package/dist/synthesis/StreamlabsPollyTTS.js +1 -1
  142. package/dist/synthesis/StreamlabsPollyTTS.js.map +1 -1
  143. package/dist/synthesis/SvoxPicoTTS.js +6 -6
  144. package/dist/synthesis/SvoxPicoTTS.js.map +1 -1
  145. package/dist/synthesis/VitsTTS.js +2 -2
  146. package/dist/synthesis/VitsTTS.js.map +1 -1
  147. package/dist/tests/Test.js +1 -47
  148. package/dist/tests/Test.js.map +1 -1
  149. package/dist/text-language-detection/FastTextLanguageDetection.js +2 -2
  150. package/dist/text-language-detection/FastTextLanguageDetection.js.map +1 -1
  151. package/dist/typings/TypedArray.d.ts +4 -0
  152. package/dist/typings/TypedArray.js +2 -0
  153. package/dist/typings/TypedArray.js.map +1 -0
  154. package/dist/utilities/BinaryArrayConversion.d.ts +12 -22
  155. package/dist/utilities/BinaryArrayConversion.js +40 -90
  156. package/dist/utilities/BinaryArrayConversion.js.map +1 -1
  157. package/dist/utilities/BinaryUtilities.d.ts +13 -0
  158. package/dist/utilities/BinaryUtilities.js +113 -0
  159. package/dist/utilities/BinaryUtilities.js.map +1 -0
  160. package/dist/utilities/Compression.js +7 -6
  161. package/dist/utilities/Compression.js.map +1 -1
  162. package/dist/utilities/FileDownloader.js +26 -47
  163. package/dist/utilities/FileDownloader.js.map +1 -1
  164. package/dist/utilities/FileReader.d.ts +14 -0
  165. package/dist/utilities/FileReader.js +71 -0
  166. package/dist/utilities/FileReader.js.map +1 -0
  167. package/dist/utilities/FileSystem.d.ts +19 -16
  168. package/dist/utilities/FileSystem.js +170 -109
  169. package/dist/utilities/FileSystem.js.map +1 -1
  170. package/dist/utilities/FileWriter.d.ts +12 -0
  171. package/dist/utilities/FileWriter.js +60 -0
  172. package/dist/utilities/FileWriter.js.map +1 -0
  173. package/dist/utilities/NpmUtilities.d.ts +1 -0
  174. package/dist/utilities/NpmUtilities.js +14 -0
  175. package/dist/utilities/NpmUtilities.js.map +1 -0
  176. package/dist/utilities/PackageManager.js +7 -5
  177. package/dist/utilities/PackageManager.js.map +1 -1
  178. package/dist/utilities/PathUtilities.d.ts +8 -0
  179. package/dist/utilities/PathUtilities.js +28 -7
  180. package/dist/utilities/PathUtilities.js.map +1 -1
  181. package/dist/utilities/SignalChannel.d.ts +3 -1
  182. package/dist/utilities/SignalChannel.js +9 -5
  183. package/dist/utilities/SignalChannel.js.map +1 -1
  184. package/dist/utilities/StringBuilder.d.ts +10 -0
  185. package/dist/utilities/StringBuilder.js +39 -0
  186. package/dist/utilities/StringBuilder.js.map +1 -0
  187. package/dist/utilities/StringUtilities.js.map +1 -1
  188. package/dist/utilities/TarballMaker.js +6 -7
  189. package/dist/utilities/TarballMaker.js.map +1 -1
  190. package/dist/utilities/Timer.js +2 -2
  191. package/dist/utilities/Timer.js.map +1 -1
  192. package/dist/utilities/Utilities.d.ts +11 -5
  193. package/dist/utilities/Utilities.js +69 -33
  194. package/dist/utilities/Utilities.js.map +1 -1
  195. package/dist/utilities/VirtualFileReadStream.d.ts +3 -3
  196. package/dist/utilities/VirtualFileReadStream.js.map +1 -1
  197. package/dist/utilities/WasmMemoryManager.d.ts +5 -2
  198. package/dist/utilities/WasmMemoryManager.js +15 -4
  199. package/dist/utilities/WasmMemoryManager.js.map +1 -1
  200. package/docs/API.md +1 -1
  201. package/docs/Licenses.md +3 -0
  202. package/docs/Options.md +9 -3
  203. package/docs/Tasklist.md +0 -1
  204. package/docs/Technical.md +2 -2
  205. package/package.json +20 -22
  206. package/src/alignment/DTWSequenceAlignment.ts +5 -5
  207. package/src/alignment/SpeechAlignment.ts +6 -6
  208. package/src/api/Alignment.ts +65 -12
  209. package/src/api/Denoising.ts +97 -17
  210. package/src/api/SourceSeparation.ts +11 -8
  211. package/src/api/SpeechLanguageDetection.ts +4 -4
  212. package/src/api/Synthesis.ts +15 -11
  213. package/src/api/VoiceActivityDetection.ts +2 -2
  214. package/src/audio/AudioBufferConversion.ts +84 -45
  215. package/src/audio/AudioPlayer.ts +155 -53
  216. package/src/audio/AudioUtilities.ts +38 -22
  217. package/src/audio/SoxPath.ts +3 -3
  218. package/src/build-tools/MakeTarballsForInstalledPackages.ts +3 -3
  219. package/src/cli/CLI.ts +30 -36
  220. package/src/cli/CLIConfigFile.ts +2 -2
  221. package/src/cli/CLIOptions.ts +4 -1
  222. package/src/codecs/FFMpegTranscoder.ts +11 -11
  223. package/src/codecs/TIMITCodec.ts +5 -4
  224. package/src/codecs/WaveCodec.ts +42 -39
  225. package/src/data-structures/DynamicTypedArray.ts +64 -0
  226. package/src/denoising/NSNet2.ts +182 -0
  227. package/src/denoising/RNNoise.ts +3 -3
  228. package/src/dsp/FFT.ts +21 -1
  229. package/src/encodings/Ascii.ts +60 -0
  230. package/src/encodings/Base64.ts +157 -0
  231. package/src/encodings/Hex.ts +67 -0
  232. package/src/{utilities → encodings}/LEB128.ts +4 -4
  233. package/src/{utilities → encodings}/LPVarInt.ts +6 -6
  234. package/src/encodings/TextEncodingsCommon.ts +4 -0
  235. package/src/encodings/Utf16.ts +52 -0
  236. package/src/encodings/Utf32.ts +62 -0
  237. package/src/encodings/Utf8.ts +117 -0
  238. package/src/math/MedianFilter.ts +0 -2
  239. package/src/nlp/JapaneseSegmentation.ts +2 -2
  240. package/src/recognition/GoogleCloudSTT.ts +2 -1
  241. package/src/recognition/SileroSTT.ts +3 -3
  242. package/src/recognition/VoskSTT.ts +3 -3
  243. package/src/recognition/WhisperCppSTT.ts +4 -5
  244. package/src/recognition/WhisperSTT.ts +8 -7
  245. package/src/server/Client.ts +4 -3
  246. package/src/server/Server.ts +6 -5
  247. package/src/server/Worker.ts +1 -1
  248. package/src/source-separation/MDXNetSourceSeparation.ts +1 -1
  249. package/src/speech-search/DTWSpeechSearch.ts +36 -7
  250. package/src/subtitles/Subtitles.ts +3 -3
  251. package/src/synthesis/AzureCognitiveServicesTTS.ts +18 -15
  252. package/src/synthesis/CoquiServerTTS.ts +2 -2
  253. package/src/synthesis/ElevenlabsTTS.ts +1 -1
  254. package/src/synthesis/EspeakTTS.ts +0 -15
  255. package/src/synthesis/FliteTTS.ts +7 -8
  256. package/src/synthesis/GoogleCloudTTS.ts +3 -2
  257. package/src/synthesis/GoogleTranslateTTS.ts +5 -4
  258. package/src/synthesis/MicrosoftEdgeTTS.ts +47 -15
  259. package/src/synthesis/SapiTTS.ts +1 -1
  260. package/src/synthesis/StreamlabsPollyTTS.ts +1 -1
  261. package/src/synthesis/SvoxPicoTTS.ts +8 -8
  262. package/src/synthesis/VitsTTS.ts +2 -2
  263. package/src/tests/Test.ts +1 -60
  264. package/src/text-language-detection/FastTextLanguageDetection.ts +2 -2
  265. package/src/typings/Fillers.d.ts +2 -4
  266. package/src/typings/TypedArray.ts +5 -0
  267. package/src/utilities/BinaryArrayConversion.ts +51 -125
  268. package/src/utilities/BinaryUtilities.ts +138 -0
  269. package/src/utilities/Compression.ts +7 -6
  270. package/src/utilities/FileDownloader.ts +27 -52
  271. package/src/utilities/FileReader.ts +89 -0
  272. package/src/utilities/FileSystem.ts +213 -120
  273. package/src/utilities/FileWriter.ts +72 -0
  274. package/src/utilities/NpmUtilities.ts +23 -0
  275. package/src/utilities/PackageManager.ts +8 -5
  276. package/src/utilities/PathUtilities.ts +36 -7
  277. package/src/utilities/SignalChannel.ts +14 -7
  278. package/src/utilities/StringBuilder.ts +45 -0
  279. package/src/utilities/StringUtilities.ts +2 -0
  280. package/src/utilities/TarballMaker.ts +6 -7
  281. package/src/utilities/Timer.ts +4 -2
  282. package/src/utilities/Utilities.ts +79 -45
  283. package/src/utilities/VirtualFileReadStream.ts +5 -5
  284. package/src/utilities/WasmMemoryManager.ts +20 -6
  285. package/tsconfig.json +96 -0
  286. package/dist/utilities/DynamicUint8Array.d.ts +0 -9
  287. package/dist/utilities/DynamicUint8Array.js +0 -31
  288. package/dist/utilities/DynamicUint8Array.js.map +0 -1
  289. package/dist/utilities/LEB128.js.map +0 -1
  290. package/dist/utilities/LPVarInt.js.map +0 -1
  291. package/dist/utilities/Queue.js.map +0 -1
  292. package/dist/utilities/WindowedList.js.map +0 -1
  293. package/src/utilities/DynamicUint8Array.ts +0 -39
  294. /package/dist/{utilities → data-structures}/Queue.d.ts +0 -0
  295. /package/dist/{utilities → data-structures}/Queue.js +0 -0
  296. /package/dist/{utilities → data-structures}/WindowedList.d.ts +0 -0
  297. /package/dist/{utilities → data-structures}/WindowedList.js +0 -0
  298. /package/src/{utilities → data-structures}/Queue.ts +0 -0
  299. /package/src/{utilities → data-structures}/WindowedList.ts +0 -0
@@ -2,157 +2,168 @@ import * as fsExtra from 'fs-extra/esm'
2
2
  import gracefulFS from 'graceful-fs'
3
3
  import * as os from 'node:os'
4
4
 
5
- import path from 'node:path'
6
5
  import { promisify } from 'node:util'
7
- import { OpenPromise } from './OpenPromise.js'
8
- import { getRandomHexString } from './Utilities.js'
6
+ import { getRandomHexString, parseJson, stringifyAndFormatJson } from './Utilities.js'
9
7
  import { appName } from '../api/Common.js'
10
- import { getAppTempDir } from './PathUtilities.js'
11
- import { writeFile as nodeFsWriteFile } from 'node:fs/promises'
8
+ import { getAppTempDir, getDirName, joinPath, normalizePath, parsePath } from './PathUtilities.js'
12
9
 
13
- export const readFile = promisify(gracefulFS.readFile)
14
- //export const gracefulFsWriteFile = promisify(gracefulFS.writeFile)
10
+ import { createDynamicUint8Array } from '../data-structures/DynamicTypedArray.js'
11
+ import { ChunkedUtf8Decoder } from '../encodings/Utf8.js'
12
+ import { FileWriter } from './FileWriter.js'
13
+ import { FileReader } from './FileReader.js'
15
14
 
16
- export const readdir = promisify(gracefulFS.readdir)
17
- export const stat = promisify(gracefulFS.stat)
18
15
  export const open = promisify(gracefulFS.open)
19
16
  export const close = promisify(gracefulFS.close)
17
+
18
+ export const read = promisify(gracefulFS.read)
19
+ export const write = promisify(gracefulFS.write)
20
+
21
+ export const existsSync = gracefulFS.existsSync
22
+
23
+ export const stat = promisify(gracefulFS.stat)
20
24
  export const chmod = promisify(gracefulFS.chmod)
21
- export const copyFile = promisify(gracefulFS.copyFile)
22
25
  export const access = promisify(gracefulFS.access)
23
26
 
24
- export const createReadStream = gracefulFS.createReadStream
25
- export const createWriteStream = gracefulFS.createWriteStream
26
- export const existsSync = gracefulFS.existsSync
27
+ export const readdir = promisify(gracefulFS.readdir)
28
+ export const copyFile = promisify(gracefulFS.copyFile)
27
29
 
28
30
  export const remove = fsExtra.remove
29
31
  export const copy = fsExtra.copy
30
- // const outputFile = fsExtra.outputFile
31
32
 
32
- export async function readDirRecursive(dir: string, fileFilter?: (filePath: string) => boolean) {
33
- if (!(await stat(dir)).isDirectory()) {
34
- throw new Error(`'${dir}' is not a directory`)
35
- }
33
+ ///////////////////////////////////////////////////////////////////////////////////////////
34
+ // File read operations
35
+ ///////////////////////////////////////////////////////////////////////////////////////////
36
+ export async function readFileAsBinary(filePath: string) {
37
+ const chunkSize = 2 ** 20
36
38
 
37
- const filenamesInDir = await readdir(dir)
38
- const filesInDir = filenamesInDir.map(filename => path.join(dir, filename))
39
+ const fileInfo = await stat(filePath)
40
+ const fileSize = fileInfo.size
39
41
 
40
- const result: string[] = []
41
- const subDirectories: string[] = []
42
+ const fileReader = new FileReader(filePath)
43
+ const buffer = new Uint8Array(chunkSize)
44
+ const result = createDynamicUint8Array(fileSize)
42
45
 
43
- for (const filePath of filesInDir) {
44
- if ((await stat(filePath)).isDirectory()) {
45
- subDirectories.push(filePath)
46
- } else {
47
- if (fileFilter && !fileFilter(filePath)) {
48
- continue
49
- }
46
+ while (!fileReader.isFinished) {
47
+ const chunk = await fileReader.readChunk(buffer)
50
48
 
51
- result.push(filePath)
52
- }
49
+ result.addArray(chunk)
53
50
  }
54
51
 
55
- for (const subDirectory of subDirectories) {
56
- const filesInSubdirectory = await readDirRecursive(subDirectory, fileFilter)
57
- result.push(...filesInSubdirectory)
58
- }
59
-
60
- return result
52
+ return result.toTypedArray()
61
53
  }
62
54
 
63
- export async function isFileIsUpToDate(filePath: string, timeRangeSeconds: number) {
64
- const fileUpdateTime = (await stat(filePath)).mtime.valueOf()
55
+ export async function readFileAsUtf8(filePath: string) {
56
+ const chunkSize = 2 ** 20
65
57
 
66
- const currentTime = (new Date()).valueOf()
58
+ const fileReader = new FileReader(filePath)
59
+ const buffer = new Uint8Array(chunkSize)
67
60
 
68
- const differenceInMilliseconds = currentTime - fileUpdateTime
61
+ const result = new ChunkedUtf8Decoder()
69
62
 
70
- const differenceInSeconds = differenceInMilliseconds / 1000
63
+ while (!fileReader.isFinished) {
64
+ const chunk = await fileReader.readChunk(buffer)
65
+
66
+ result.writeChunk(chunk)
67
+ }
71
68
 
72
- return differenceInSeconds <= timeRangeSeconds
69
+ return result.toString()
73
70
  }
74
71
 
75
- export async function computeFileSha256Hex(filePath: string) {
76
- const resultOpenPromise = new OpenPromise<string>()
72
+ export async function readAndParseJsonFile(jsonFilePath: string, useJson5 = false) {
73
+ const textContent = await readFileAsUtf8(jsonFilePath)
77
74
 
78
- const crypto = await import('crypto')
79
- const hash = crypto.createHash('sha256')
75
+ return parseJson(textContent, useJson5)
76
+ }
77
+
78
+ ///////////////////////////////////////////////////////////////////////////////////////////
79
+ // File write operations
80
+ ///////////////////////////////////////////////////////////////////////////////////////////
81
+ export async function writeFile(filePath: string, content: Uint8Array | string) {
82
+ if (content instanceof Uint8Array) {
83
+ return writeBinaryFile(filePath, content)
84
+ } else if (typeof content === 'string') {
85
+ return writeUtf8File(filePath, content)
86
+ } else {
87
+ throw new Error(`Content can only be a Uint8Array or string`)
88
+ }
89
+ }
80
90
 
81
- const readStream = createReadStream(filePath)
91
+ export async function writeBinaryFile(filePath: string, content: Uint8Array) {
92
+ const maxChunkSize = 2 ** 20
82
93
 
83
- readStream.on('data', data => hash.update(data))
84
- readStream.on('error', error => resultOpenPromise.reject(error))
85
- readStream.on('end', () => resultOpenPromise.resolve(hash.digest('hex')))
94
+ const fileDir = getDirName(filePath)
86
95
 
87
- return resultOpenPromise.promise
88
- }
96
+ await ensureDir(fileDir)
89
97
 
90
- export async function readAndParseJsonFile(jsonFilePath: string, useJson5 = false) {
91
- const fileContent = await readFile(jsonFilePath, { encoding: 'utf-8' })
98
+ const fileWriter = new FileWriter(filePath)
92
99
 
93
- if (useJson5) {
94
- const { default: JSON5 } = await import('json5')
100
+ let readOffset = 0
95
101
 
96
- return JSON5.parse(fileContent)
97
- } else {
98
- return JSON.parse(fileContent)
102
+ while (true) {
103
+ const chunk = content.subarray(readOffset, readOffset + maxChunkSize)
104
+
105
+ if (chunk.length === 0) {
106
+ break
107
+ }
108
+
109
+ await fileWriter.write(chunk)
110
+
111
+ readOffset += chunk.length
99
112
  }
113
+
114
+ await fileWriter.dispose()
100
115
  }
101
116
 
102
- export async function writeFile(filePath: string, data: string | NodeJS.ArrayBufferView, options?: fsExtra.WriteFileOptions) {
103
- const fileDir = path.dirname(filePath)
117
+ export async function writeUtf8File(filePath: string, content: string) {
118
+ const maxChunkSize = 2 ** 20
119
+
120
+ const fileDir = getDirName(filePath)
104
121
 
105
122
  await ensureDir(fileDir)
106
123
 
107
- return nodeFsWriteFile(filePath, data, options)
108
- }
124
+ const fileWriter = new FileWriter(filePath)
109
125
 
110
- export async function writeFileSafe(filePath: string, data: string | NodeJS.ArrayBufferView, options?: fsExtra.WriteFileOptions) {
111
- const tempDir = getAppTempDir(appName)
112
- const tempFilePath = path.join(tempDir, `${getRandomHexString(16)}.partial`)
126
+ const textEncoder = new TextEncoder()
113
127
 
114
- await writeFile(tempFilePath, data, options)
128
+ let readOffset = 0
115
129
 
116
- await move(tempFilePath, filePath)
117
- }
130
+ while (true) {
131
+ const stringChunk = content.substring(readOffset, readOffset + maxChunkSize)
118
132
 
119
- export function getAppDataDir(appName: string) {
120
- let dataDir: string
133
+ if (stringChunk.length === 0) {
134
+ break
135
+ }
121
136
 
122
- const platform = process.platform
123
- const homeDir = os.homedir()
137
+ const chunk = textEncoder.encode(stringChunk)
124
138
 
125
- if (platform == 'win32') {
126
- dataDir = path.join(homeDir, 'AppData', 'Local', appName)
127
- } else if (platform == 'darwin') {
128
- dataDir = path.join(homeDir, 'Library', 'Application Support', appName)
129
- } else if (platform == 'linux') {
130
- dataDir = path.join(homeDir, '.local', 'share', appName)
131
- } else {
132
- throw new Error(`Unsupport platform ${platform}`)
139
+ await fileWriter.write(chunk)
140
+
141
+ readOffset += stringChunk.length
133
142
  }
134
143
 
135
- return dataDir
144
+ await fileWriter.dispose()
136
145
  }
137
146
 
138
- export async function chmodRecursive(rootPath: string, newMode: number) {
139
- const rootPathStat = await stat(rootPath)
147
+ export async function writeJsonFile(filePath: string, content: any, useJson5 = false) {
148
+ const textContent = await stringifyAndFormatJson(content, useJson5)
140
149
 
141
- await chmod(rootPath, newMode)
150
+ await writeUtf8File(filePath, textContent)
151
+ }
142
152
 
143
- if (rootPathStat.isDirectory()) {
144
- const fileList = await readdir(rootPath)
153
+ export async function writeFileSafe(filePath: string, content: Uint8Array | string) {
154
+ const tempDir = getAppTempDir(appName)
155
+ const tempFilePath = joinPath(tempDir, `${getRandomHexString(16)}.partial`)
145
156
 
146
- for (const filename of fileList) {
147
- const filePath = path.join(rootPath, filename)
157
+ await writeFile(tempFilePath, content)
148
158
 
149
- await chmodRecursive(filePath, newMode)
150
- }
151
- }
159
+ await move(tempFilePath, filePath)
152
160
  }
153
161
 
162
+ ///////////////////////////////////////////////////////////////////////////////////////////
163
+ // Directory operations
164
+ ///////////////////////////////////////////////////////////////////////////////////////////
154
165
  export async function ensureDir(dirPath: string) {
155
- dirPath = path.normalize(dirPath)
166
+ dirPath = normalizePath(dirPath)
156
167
 
157
168
  if (existsSync(dirPath)) {
158
169
  const dirStats = await stat(dirPath)
@@ -165,9 +176,75 @@ export async function ensureDir(dirPath: string) {
165
176
  }
166
177
  }
167
178
 
179
+ export async function testDirectoryIsWritable(dir: string) {
180
+ const testFileName = joinPath(dir, getRandomHexString(16))
181
+
182
+ try {
183
+ await fsExtra.createFile(testFileName)
184
+ await remove(testFileName)
185
+ } catch (e) {
186
+ return false
187
+ }
188
+
189
+ return true
190
+ }
191
+
192
+ export async function readDirRecursive(dir: string, pathFilter?: (filePath: string) => boolean) {
193
+ if (!(await stat(dir)).isDirectory()) {
194
+ throw new Error(`'${dir}' is not a directory`)
195
+ }
196
+
197
+ const filenamesInDir = await readdir(dir)
198
+ const filesInDir = filenamesInDir.map(filename => joinPath(dir, filename))
199
+
200
+ const result: string[] = []
201
+ const subDirectories: string[] = []
202
+
203
+ for (const filePath of filesInDir) {
204
+ if ((await stat(filePath)).isDirectory()) {
205
+ subDirectories.push(filePath)
206
+ } else {
207
+ if (pathFilter && !pathFilter(filePath)) {
208
+ continue
209
+ }
210
+
211
+ result.push(filePath)
212
+ }
213
+ }
214
+
215
+ for (const subDirectory of subDirectories) {
216
+ const filesInSubdirectory = await readDirRecursive(subDirectory, pathFilter)
217
+ result.push(...filesInSubdirectory)
218
+ }
219
+
220
+ return result
221
+ }
222
+
223
+ export function getAppDataDir(appName: string) {
224
+ let dataDir: string
225
+
226
+ const platform = process.platform
227
+ const homeDir = os.homedir()
228
+
229
+ if (platform == 'win32') {
230
+ dataDir = joinPath(homeDir, 'AppData', 'Local', appName)
231
+ } else if (platform == 'darwin') {
232
+ dataDir = joinPath(homeDir, 'Library', 'Application Support', appName)
233
+ } else if (platform == 'linux') {
234
+ dataDir = joinPath(homeDir, '.local', 'share', appName)
235
+ } else {
236
+ throw new Error(`Unsupport platform ${platform}`)
237
+ }
238
+
239
+ return dataDir
240
+ }
241
+
242
+ ///////////////////////////////////////////////////////////////////////////////////////////
243
+ // Copy operations
244
+ ///////////////////////////////////////////////////////////////////////////////////////////
168
245
  export async function move(source: string, dest: string) {
169
- source = path.normalize(source)
170
- dest = path.normalize(dest)
246
+ source = normalizePath(source)
247
+ dest = normalizePath(dest)
171
248
 
172
249
  if (existsSync(dest)) {
173
250
  const destPathExistsAndIsWritable = await existsAndIsWritable(dest)
@@ -176,7 +253,7 @@ export async function move(source: string, dest: string) {
176
253
  throw new Error(`The destination path '${dest}' exists but is not writable. There may be a permissions or locking issue.`)
177
254
  }
178
255
  } else {
179
- const destDir = path.parse(dest).dir
256
+ const destDir = parsePath(dest).dir
180
257
  const destDirIsWritable = await testDirectoryIsWritable(destDir)
181
258
 
182
259
  if (!destDirIsWritable) {
@@ -187,6 +264,9 @@ export async function move(source: string, dest: string) {
187
264
  return fsExtra.move(source, dest, { overwrite: true })
188
265
  }
189
266
 
267
+ ///////////////////////////////////////////////////////////////////////////////////////////
268
+ // Misc operations
269
+ ///////////////////////////////////////////////////////////////////////////////////////////
190
270
  export async function existsAndIsWritable(targetPath: string) {
191
271
  try {
192
272
  await access(targetPath, gracefulFS.constants.W_OK);
@@ -197,36 +277,49 @@ export async function existsAndIsWritable(targetPath: string) {
197
277
  return true
198
278
  }
199
279
 
200
- export async function testDirectoryIsWritable(dir: string) {
201
- const testFileName = path.join(dir, getRandomHexString(16))
280
+ export async function chmodRecursive(rootPath: string, newMode: number) {
281
+ const rootPathStat = await stat(rootPath)
202
282
 
203
- try {
204
- await fsExtra.createFile(testFileName)
205
- await remove(testFileName)
206
- } catch (e) {
207
- return false
283
+ await chmod(rootPath, newMode)
284
+
285
+ if (rootPathStat.isDirectory()) {
286
+ const fileList = await readdir(rootPath)
287
+
288
+ for (const filename of fileList) {
289
+ const filePath = joinPath(rootPath, filename)
290
+
291
+ await chmodRecursive(filePath, newMode)
292
+ }
208
293
  }
294
+ }
209
295
 
210
- return true
296
+ export async function isFileIsUpToDate(filePath: string, maxTimeDifferenceSeconds: number) {
297
+ const fileUpdateTime = (await stat(filePath)).mtime.valueOf()
298
+
299
+ const currentTime = (new Date()).valueOf()
300
+
301
+ const differenceInMilliseconds = currentTime - fileUpdateTime
302
+
303
+ const differenceInSeconds = differenceInMilliseconds / 1000
304
+
305
+ return differenceInSeconds <= maxTimeDifferenceSeconds
211
306
  }
212
307
 
213
- export async function copyFileAlternative(source: string, dest: string) {
214
- return new Promise<void>((resolve, reject) => {
215
- const readStream = createReadStream(source)
216
- const writeStream = createWriteStream(dest)
308
+ export async function computeFileSha256Hex(filePath: string) {
309
+ const crypto = await import('crypto')
310
+
311
+ const hash = crypto.createHash('sha256')
217
312
 
218
- readStream.on('error', (err: any) => {
219
- reject(err)
220
- })
313
+ const fileReader = new FileReader(filePath)
314
+ const buffer = new Uint8Array(2 ** 16)
221
315
 
222
- writeStream.on('error', (err: any) => {
223
- reject(err)
224
- })
316
+ while (!fileReader.isFinished) {
317
+ const chunk = await fileReader.readChunk(buffer)
225
318
 
226
- readStream.pipe(writeStream)
319
+ hash.update(chunk)
320
+ }
227
321
 
228
- readStream.on('end', () => {
229
- resolve()
230
- })
231
- })
322
+ const result = hash.digest('hex')
323
+
324
+ return result
232
325
  }
@@ -0,0 +1,72 @@
1
+ import { write, open, close } from "./FileSystem.js"
2
+
3
+ export class FileWriter {
4
+ private fileHandle?: number
5
+ private disposed = false
6
+ private writeOffset = 0
7
+
8
+ constructor(public readonly filePath: string) {
9
+ }
10
+
11
+ async write(chunk: Uint8Array) {
12
+ if (this.isDisposed) {
13
+ throw new Error(`FileWriter has been disposed`)
14
+ }
15
+
16
+ await this.openIfNeeded()
17
+
18
+ let chunkReadOffset = 0
19
+
20
+ while (chunkReadOffset < chunk.length) {
21
+ let bytesWritten: number
22
+
23
+ try {
24
+ ({ bytesWritten } = await write(this.fileHandle!, chunk, chunkReadOffset, undefined, this.writeOffset))
25
+ } catch (e) {
26
+ await this.dispose()
27
+
28
+ throw e
29
+ }
30
+
31
+ chunkReadOffset += bytesWritten
32
+ this.writeOffset += bytesWritten
33
+ }
34
+ }
35
+
36
+ private async openIfNeeded() {
37
+ if (this.isDisposed) {
38
+ throw new Error(`FileWriter has been disposed`)
39
+ }
40
+
41
+ if (this.isOpened) {
42
+ return
43
+ }
44
+
45
+ this.fileHandle = await open(this.filePath, 'w')
46
+ }
47
+
48
+ async dispose() {
49
+ if (this.isDisposed) {
50
+ return
51
+ }
52
+
53
+ if (this.isOpened) {
54
+ try {
55
+ await close(this.fileHandle!)
56
+ } catch (e) {
57
+ }
58
+ }
59
+
60
+ this.disposed = true
61
+ this.writeOffset = 0
62
+ this.fileHandle = undefined
63
+ }
64
+
65
+ get isOpened() {
66
+ return this.fileHandle !== undefined
67
+ }
68
+
69
+ get isDisposed() {
70
+ return this.disposed
71
+ }
72
+ }
@@ -0,0 +1,23 @@
1
+ import { request } from 'gaxios'
2
+
3
+ export async function getPackageLatestVersion(packageName: string, timeout = 10000) {
4
+ const response = await request<any>({
5
+ method: 'GET',
6
+
7
+ url: `https://registry.npmjs.org/${packageName}/latest`,
8
+
9
+ params: {
10
+ },
11
+
12
+ headers: {
13
+ },
14
+
15
+ responseType: 'json',
16
+
17
+ timeout,
18
+ })
19
+
20
+ const result = response.data
21
+
22
+ return result.version
23
+ }
@@ -1,9 +1,8 @@
1
- import path from 'node:path'
2
1
  import { downloadAndExtractTarball } from './FileDownloader.js'
3
2
  import { getAppDataDir, ensureDir, existsSync, remove } from './FileSystem.js'
4
3
  import { appName } from '../api/Common.js'
5
4
  import { GaxiosOptions } from 'gaxios'
6
- import { getAppTempDir } from './PathUtilities.js'
5
+ import { getAppTempDir, joinPath } from './PathUtilities.js'
7
6
  import { getGlobalOption } from '../api/GlobalOptions.js'
8
7
 
9
8
  export async function loadPackage(packageName: string) {
@@ -11,7 +10,7 @@ export async function loadPackage(packageName: string) {
11
10
 
12
11
  const packagesPath = await ensureAndGetPackagesDir()
13
12
 
14
- const packagePath = path.join(packagesPath, packageName)
13
+ const packagePath = joinPath(packagesPath, packageName)
15
14
 
16
15
  if (existsSync(packagePath)) {
17
16
  return packagePath
@@ -44,7 +43,7 @@ export async function removePackage(packageName: string) {
44
43
 
45
44
  const packagesPath = await ensureAndGetPackagesDir()
46
45
 
47
- const packagePath = path.join(packagesPath, packageName)
46
+ const packagePath = joinPath(packagesPath, packageName)
48
47
 
49
48
  await remove(packagePath)
50
49
  }
@@ -52,7 +51,7 @@ export async function removePackage(packageName: string) {
52
51
  export async function ensureAndGetPackagesDir() {
53
52
  const dataPath = getAppDataDir(appName)
54
53
 
55
- const packagesPath = path.join(dataPath, 'packages')
54
+ const packagesPath = joinPath(dataPath, 'packages')
56
55
 
57
56
  await ensureDir(packagesPath)
58
57
 
@@ -209,4 +208,8 @@ const packageVersionTagResolutionLookup: { [packageName: string]: string } = {
209
208
  // W2V-BERT models
210
209
  'w2v-bert-2.0-int8': '20240517',
211
210
  'w2v-bert-2.0-uint8': '20240517',
211
+
212
+ // NSNet2 models
213
+ 'nsnet2-20ms-baseline': '20242610',
214
+ 'nsnet2-20ms-48k-baseline': '20242610',
212
215
  }
@@ -1,14 +1,15 @@
1
- import path from 'node:path'
1
+ import * as NodePath from 'node:path'
2
2
  import { fileURLToPath } from 'node:url'
3
3
  import * as os from 'node:os'
4
4
 
5
5
  export function getModuleRootDir() {
6
- const currentScriptDir = path.dirname(fileURLToPath(import.meta.url))
7
- return path.resolve(currentScriptDir, '..', '..')
6
+ const currentScriptDir = getDirName(fileURLToPath(import.meta.url))
7
+
8
+ return resolvePath(currentScriptDir, '..', '..')
8
9
  }
9
10
 
10
11
  export function resolveToModuleRootDir(relativePath: string) {
11
- return path.resolve(getModuleRootDir(), relativePath)
12
+ return resolvePath(getModuleRootDir(), relativePath)
12
13
  }
13
14
 
14
15
  export function getLowercaseFileExtension(filename: string) {
@@ -28,14 +29,42 @@ export function getAppTempDir(appName: string) {
28
29
  const homeDir = os.homedir()
29
30
 
30
31
  if (platform == 'win32') {
31
- tempDir = path.join(homeDir, 'AppData', 'Local', 'Temp', appName)
32
+ tempDir = joinPath(homeDir, 'AppData', 'Local', 'Temp', appName)
32
33
  } else if (platform == 'darwin') {
33
- tempDir = path.join(homeDir, 'Library', 'Caches', appName)
34
+ tempDir = joinPath(homeDir, 'Library', 'Caches', appName)
34
35
  } else if (platform == 'linux') {
35
- tempDir = path.join(homeDir, '.cache', appName)
36
+ tempDir = joinPath(homeDir, '.cache', appName)
36
37
  } else {
37
38
  throw new Error(`Unsupport platform ${platform}`)
38
39
  }
39
40
 
40
41
  return tempDir
41
42
  }
43
+
44
+ export function joinPath(...paths: string[]) {
45
+ return NodePath.join(...paths)
46
+ }
47
+
48
+ export function resolvePath(...paths: string[]) {
49
+ return NodePath.resolve(...paths)
50
+ }
51
+
52
+ export function normalizePath(path: string) {
53
+ return NodePath.normalize(path)
54
+ }
55
+
56
+ export function getBaseName(path: string) {
57
+ return NodePath.basename(path)
58
+ }
59
+
60
+ export function getDirName(path: string) {
61
+ return NodePath.dirname(path)
62
+ }
63
+
64
+ export function getFileNameWithoutExtension(filePath: string) {
65
+ return NodePath.parse(filePath).name
66
+ }
67
+
68
+ export function parsePath(path: string) {
69
+ return NodePath.parse(path)
70
+ }