echogarden 1.8.6 → 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 +136 -50
  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 -5
  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 +0 -25
  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 -17
  168. package/dist/utilities/FileSystem.js +170 -106
  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 -4
  193. package/dist/utilities/Utilities.js +70 -18
  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 -3
  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 +156 -54
  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 -7
  262. package/src/synthesis/VitsTTS.ts +2 -2
  263. package/src/tests/Test.ts +0 -30
  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 +215 -116
  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 +80 -23
  283. package/src/utilities/VirtualFileReadStream.ts +5 -5
  284. package/src/utilities/WasmMemoryManager.ts +21 -5
  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,166 +2,249 @@ 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'
8
+ import { getAppTempDir, getDirName, joinPath, normalizePath, parsePath } from './PathUtilities.js'
9
+
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'
11
14
 
12
- export const readFile = promisify(gracefulFS.readFile)
13
- //export const writeFile = promisify(gracefulFS.writeFile)
14
- export const readdir = promisify(gracefulFS.readdir)
15
- export const stat = promisify(gracefulFS.stat)
16
15
  export const open = promisify(gracefulFS.open)
17
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)
18
24
  export const chmod = promisify(gracefulFS.chmod)
19
- export const copyFile = promisify(gracefulFS.copyFile)
20
25
  export const access = promisify(gracefulFS.access)
21
26
 
22
- export const createReadStream = gracefulFS.createReadStream
23
- export const createWriteStream = gracefulFS.createWriteStream
24
- export const existsSync = gracefulFS.existsSync
27
+ export const readdir = promisify(gracefulFS.readdir)
28
+ export const copyFile = promisify(gracefulFS.copyFile)
25
29
 
26
30
  export const remove = fsExtra.remove
27
31
  export const copy = fsExtra.copy
28
- export const outputFile = fsExtra.outputFile
29
32
 
30
- export async function readDirRecursive(dir: string, fileFilter?: (filePath: string) => boolean) {
31
- if (!(await stat(dir)).isDirectory()) {
32
- throw new Error(`'${dir}' is not a directory`)
33
- }
33
+ ///////////////////////////////////////////////////////////////////////////////////////////
34
+ // File read operations
35
+ ///////////////////////////////////////////////////////////////////////////////////////////
36
+ export async function readFileAsBinary(filePath: string) {
37
+ const chunkSize = 2 ** 20
34
38
 
35
- const filenamesInDir = await readdir(dir)
36
- const filesInDir = filenamesInDir.map(filename => path.join(dir, filename))
39
+ const fileInfo = await stat(filePath)
40
+ const fileSize = fileInfo.size
37
41
 
38
- const result: string[] = []
39
- const subDirectories: string[] = []
42
+ const fileReader = new FileReader(filePath)
43
+ const buffer = new Uint8Array(chunkSize)
44
+ const result = createDynamicUint8Array(fileSize)
40
45
 
41
- for (const filePath of filesInDir) {
42
- if ((await stat(filePath)).isDirectory()) {
43
- subDirectories.push(filePath)
44
- } else {
45
- if (fileFilter && !fileFilter(filePath)) {
46
- continue
47
- }
46
+ while (!fileReader.isFinished) {
47
+ const chunk = await fileReader.readChunk(buffer)
48
48
 
49
- result.push(filePath)
50
- }
49
+ result.addArray(chunk)
51
50
  }
52
51
 
53
- for (const subDirectory of subDirectories) {
54
- const filesInSubdirectory = await readDirRecursive(subDirectory, fileFilter)
55
- result.push(...filesInSubdirectory)
52
+ return result.toTypedArray()
53
+ }
54
+
55
+ export async function readFileAsUtf8(filePath: string) {
56
+ const chunkSize = 2 ** 20
57
+
58
+ const fileReader = new FileReader(filePath)
59
+ const buffer = new Uint8Array(chunkSize)
60
+
61
+ const result = new ChunkedUtf8Decoder()
62
+
63
+ while (!fileReader.isFinished) {
64
+ const chunk = await fileReader.readChunk(buffer)
65
+
66
+ result.writeChunk(chunk)
56
67
  }
57
68
 
58
- return result
69
+ return result.toString()
59
70
  }
60
71
 
61
- export async function isFileIsUpToDate(filePath: string, timeRangeSeconds: number) {
62
- const fileUpdateTime = (await stat(filePath)).mtime.valueOf()
72
+ export async function readAndParseJsonFile(jsonFilePath: string, useJson5 = false) {
73
+ const textContent = await readFileAsUtf8(jsonFilePath)
63
74
 
64
- const currentTime = (new Date()).valueOf()
75
+ return parseJson(textContent, useJson5)
76
+ }
65
77
 
66
- const differenceInMilliseconds = currentTime - fileUpdateTime
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
+ }
67
90
 
68
- const differenceInSeconds = differenceInMilliseconds / 1000
91
+ export async function writeBinaryFile(filePath: string, content: Uint8Array) {
92
+ const maxChunkSize = 2 ** 20
69
93
 
70
- return differenceInSeconds <= timeRangeSeconds
71
- }
94
+ const fileDir = getDirName(filePath)
72
95
 
73
- export async function computeFileSha256Hex(filePath: string) {
74
- const resultOpenPromise = new OpenPromise<string>()
96
+ await ensureDir(fileDir)
75
97
 
76
- const crypto = await import('crypto')
77
- const hash = crypto.createHash('sha256')
98
+ const fileWriter = new FileWriter(filePath)
78
99
 
79
- const readStream = createReadStream(filePath)
100
+ let readOffset = 0
80
101
 
81
- readStream.on('data', data => hash.update(data))
82
- readStream.on('error', error => resultOpenPromise.reject(error))
83
- readStream.on('end', () => resultOpenPromise.resolve(hash.digest('hex')))
102
+ while (true) {
103
+ const chunk = content.subarray(readOffset, readOffset + maxChunkSize)
84
104
 
85
- return resultOpenPromise.promise
105
+ if (chunk.length === 0) {
106
+ break
107
+ }
108
+
109
+ await fileWriter.write(chunk)
110
+
111
+ readOffset += chunk.length
112
+ }
113
+
114
+ await fileWriter.dispose()
86
115
  }
87
116
 
88
- export async function readAndParseJsonFile(jsonFilePath: string, useJson5 = false) {
89
- const fileContent = await readFile(jsonFilePath, { encoding: 'utf-8' })
117
+ export async function writeUtf8File(filePath: string, content: string) {
118
+ const maxChunkSize = 2 ** 20
90
119
 
91
- if (useJson5) {
92
- const { default: JSON5 } = await import('json5')
120
+ const fileDir = getDirName(filePath)
93
121
 
94
- return JSON5.parse(fileContent)
95
- } else {
96
- return JSON.parse(fileContent)
122
+ await ensureDir(fileDir)
123
+
124
+ const fileWriter = new FileWriter(filePath)
125
+
126
+ const textEncoder = new TextEncoder()
127
+
128
+ let readOffset = 0
129
+
130
+ while (true) {
131
+ const stringChunk = content.substring(readOffset, readOffset + maxChunkSize)
132
+
133
+ if (stringChunk.length === 0) {
134
+ break
135
+ }
136
+
137
+ const chunk = textEncoder.encode(stringChunk)
138
+
139
+ await fileWriter.write(chunk)
140
+
141
+ readOffset += stringChunk.length
97
142
  }
143
+
144
+ await fileWriter.dispose()
98
145
  }
99
146
 
100
- export async function writeFile(filePath: string, data: string | NodeJS.ArrayBufferView, options?: fsExtra.WriteFileOptions) {
101
- return outputFile(filePath, data, options)
147
+ export async function writeJsonFile(filePath: string, content: any, useJson5 = false) {
148
+ const textContent = await stringifyAndFormatJson(content, useJson5)
149
+
150
+ await writeUtf8File(filePath, textContent)
102
151
  }
103
152
 
104
- export async function writeFileSafe(filePath: string, data: string | NodeJS.ArrayBufferView, options?: fsExtra.WriteFileOptions) {
153
+ export async function writeFileSafe(filePath: string, content: Uint8Array | string) {
105
154
  const tempDir = getAppTempDir(appName)
106
- const tempFilePath = path.join(tempDir, `${getRandomHexString(16)}.partial`)
155
+ const tempFilePath = joinPath(tempDir, `${getRandomHexString(16)}.partial`)
107
156
 
108
- await writeFile(tempFilePath, data, options)
157
+ await writeFile(tempFilePath, content)
109
158
 
110
159
  await move(tempFilePath, filePath)
111
160
  }
112
161
 
113
- export function getAppDataDir(appName: string) {
114
- let dataDir: string
162
+ ///////////////////////////////////////////////////////////////////////////////////////////
163
+ // Directory operations
164
+ ///////////////////////////////////////////////////////////////////////////////////////////
165
+ export async function ensureDir(dirPath: string) {
166
+ dirPath = normalizePath(dirPath)
115
167
 
116
- const platform = process.platform
117
- const homeDir = os.homedir()
168
+ if (existsSync(dirPath)) {
169
+ const dirStats = await stat(dirPath)
118
170
 
119
- if (platform == 'win32') {
120
- dataDir = path.join(homeDir, 'AppData', 'Local', appName)
121
- } else if (platform == 'darwin') {
122
- dataDir = path.join(homeDir, 'Library', 'Application Support', appName)
123
- } else if (platform == 'linux') {
124
- dataDir = path.join(homeDir, '.local', 'share', appName)
171
+ if (!dirStats.isDirectory()) {
172
+ throw new Error(`The path '${dirPath}' exists but is not a directory.`)
173
+ }
125
174
  } else {
126
- throw new Error(`Unsupport platform ${platform}`)
175
+ return fsExtra.ensureDir(dirPath)
127
176
  }
177
+ }
128
178
 
129
- return dataDir
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
130
190
  }
131
191
 
132
- export async function chmodRecursive(rootPath: string, newMode: number) {
133
- const rootPathStat = await stat(rootPath)
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
+ }
134
196
 
135
- await chmod(rootPath, newMode)
197
+ const filenamesInDir = await readdir(dir)
198
+ const filesInDir = filenamesInDir.map(filename => joinPath(dir, filename))
136
199
 
137
- if (rootPathStat.isDirectory()) {
138
- const fileList = await readdir(rootPath)
200
+ const result: string[] = []
201
+ const subDirectories: string[] = []
139
202
 
140
- for (const filename of fileList) {
141
- const filePath = path.join(rootPath, filename)
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
+ }
142
210
 
143
- await chmodRecursive(filePath, newMode)
211
+ result.push(filePath)
144
212
  }
145
213
  }
214
+
215
+ for (const subDirectory of subDirectories) {
216
+ const filesInSubdirectory = await readDirRecursive(subDirectory, pathFilter)
217
+ result.push(...filesInSubdirectory)
218
+ }
219
+
220
+ return result
146
221
  }
147
222
 
148
- export async function ensureDir(dirPath: string) {
149
- dirPath = path.normalize(dirPath)
223
+ export function getAppDataDir(appName: string) {
224
+ let dataDir: string
150
225
 
151
- if (existsSync(dirPath)) {
152
- const dirStats = await stat(dirPath)
226
+ const platform = process.platform
227
+ const homeDir = os.homedir()
153
228
 
154
- if (!dirStats.isDirectory()) {
155
- throw new Error(`The path '${dirPath}' exists but is not a directory.`)
156
- }
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)
157
235
  } else {
158
- return fsExtra.ensureDir(dirPath)
236
+ throw new Error(`Unsupport platform ${platform}`)
159
237
  }
238
+
239
+ return dataDir
160
240
  }
161
241
 
242
+ ///////////////////////////////////////////////////////////////////////////////////////////
243
+ // Copy operations
244
+ ///////////////////////////////////////////////////////////////////////////////////////////
162
245
  export async function move(source: string, dest: string) {
163
- source = path.normalize(source)
164
- dest = path.normalize(dest)
246
+ source = normalizePath(source)
247
+ dest = normalizePath(dest)
165
248
 
166
249
  if (existsSync(dest)) {
167
250
  const destPathExistsAndIsWritable = await existsAndIsWritable(dest)
@@ -170,7 +253,7 @@ export async function move(source: string, dest: string) {
170
253
  throw new Error(`The destination path '${dest}' exists but is not writable. There may be a permissions or locking issue.`)
171
254
  }
172
255
  } else {
173
- const destDir = path.parse(dest).dir
256
+ const destDir = parsePath(dest).dir
174
257
  const destDirIsWritable = await testDirectoryIsWritable(destDir)
175
258
 
176
259
  if (!destDirIsWritable) {
@@ -181,6 +264,9 @@ export async function move(source: string, dest: string) {
181
264
  return fsExtra.move(source, dest, { overwrite: true })
182
265
  }
183
266
 
267
+ ///////////////////////////////////////////////////////////////////////////////////////////
268
+ // Misc operations
269
+ ///////////////////////////////////////////////////////////////////////////////////////////
184
270
  export async function existsAndIsWritable(targetPath: string) {
185
271
  try {
186
272
  await access(targetPath, gracefulFS.constants.W_OK);
@@ -191,36 +277,49 @@ export async function existsAndIsWritable(targetPath: string) {
191
277
  return true
192
278
  }
193
279
 
194
- export async function testDirectoryIsWritable(dir: string) {
195
- const testFileName = path.join(dir, getRandomHexString(16))
280
+ export async function chmodRecursive(rootPath: string, newMode: number) {
281
+ const rootPathStat = await stat(rootPath)
196
282
 
197
- try {
198
- await fsExtra.createFile(testFileName)
199
- await remove(testFileName)
200
- } catch (e) {
201
- 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
+ }
202
293
  }
294
+ }
203
295
 
204
- 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
205
306
  }
206
307
 
207
- export async function copyFileAlternative(source: string, dest: string) {
208
- return new Promise<void>((resolve, reject) => {
209
- const readStream = createReadStream(source)
210
- const writeStream = createWriteStream(dest)
308
+ export async function computeFileSha256Hex(filePath: string) {
309
+ const crypto = await import('crypto')
310
+
311
+ const hash = crypto.createHash('sha256')
211
312
 
212
- readStream.on('error', (err: any) => {
213
- reject(err)
214
- })
313
+ const fileReader = new FileReader(filePath)
314
+ const buffer = new Uint8Array(2 ** 16)
215
315
 
216
- writeStream.on('error', (err: any) => {
217
- reject(err)
218
- })
316
+ while (!fileReader.isFinished) {
317
+ const chunk = await fileReader.readChunk(buffer)
219
318
 
220
- readStream.pipe(writeStream)
319
+ hash.update(chunk)
320
+ }
221
321
 
222
- readStream.on('end', () => {
223
- resolve()
224
- })
225
- })
322
+ const result = hash.digest('hex')
323
+
324
+ return result
226
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
+ }