echogarden 2.10.2 → 3.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 (496) hide show
  1. package/LICENSE.MIT.md +7 -0
  2. package/README.md +9 -1
  3. package/data/lexicons/heteronyms.en.json +44 -10
  4. package/data/lexicons/words.en.json +726 -22
  5. package/data/schemas/options.json +91 -153
  6. package/dist/alignment/DTWMfccSequenceAlignment.js.map +1 -1
  7. package/dist/alignment/SemanticTextAlignment.d.ts +4 -2
  8. package/dist/alignment/SemanticTextAlignment.d.ts.map +1 -1
  9. package/dist/alignment/SemanticTextAlignment.js +7 -7
  10. package/dist/alignment/SemanticTextAlignment.js.map +1 -1
  11. package/dist/alignment/SpeechAlignment.d.ts +9 -10
  12. package/dist/alignment/SpeechAlignment.d.ts.map +1 -1
  13. package/dist/alignment/SpeechAlignment.js +23 -96
  14. package/dist/alignment/SpeechAlignment.js.map +1 -1
  15. package/dist/api/APIOptions.d.ts +1 -1
  16. package/dist/api/APIOptions.d.ts.map +1 -1
  17. package/dist/api/Alignment.d.ts +8 -6
  18. package/dist/api/Alignment.d.ts.map +1 -1
  19. package/dist/api/Alignment.js +31 -40
  20. package/dist/api/Alignment.js.map +1 -1
  21. package/dist/api/Common.d.ts +7 -0
  22. package/dist/api/Common.d.ts.map +1 -1
  23. package/dist/api/Common.js.map +1 -1
  24. package/dist/api/Denoising.d.ts +5 -2
  25. package/dist/api/Denoising.d.ts.map +1 -1
  26. package/dist/api/Denoising.js +15 -15
  27. package/dist/api/Denoising.js.map +1 -1
  28. package/dist/api/GlobalOptions.d.ts +2 -8
  29. package/dist/api/GlobalOptions.d.ts.map +1 -1
  30. package/dist/api/GlobalOptions.js +2 -13
  31. package/dist/api/GlobalOptions.js.map +1 -1
  32. package/dist/api/Recognition.d.ts +11 -12
  33. package/dist/api/Recognition.d.ts.map +1 -1
  34. package/dist/api/Recognition.js +32 -82
  35. package/dist/api/Recognition.js.map +1 -1
  36. package/dist/api/SourceSeparation.d.ts +7 -2
  37. package/dist/api/SourceSeparation.d.ts.map +1 -1
  38. package/dist/api/SourceSeparation.js +12 -10
  39. package/dist/api/SourceSeparation.js.map +1 -1
  40. package/dist/api/SpeechLanguageDetection.d.ts +11 -7
  41. package/dist/api/SpeechLanguageDetection.d.ts.map +1 -1
  42. package/dist/api/SpeechLanguageDetection.js +37 -30
  43. package/dist/api/SpeechLanguageDetection.js.map +1 -1
  44. package/dist/api/SpeechSearch.d.ts +4 -1
  45. package/dist/api/SpeechSearch.d.ts.map +1 -1
  46. package/dist/api/SpeechSearch.js.map +1 -1
  47. package/dist/api/SpeechTranslation.d.ts +10 -6
  48. package/dist/api/SpeechTranslation.d.ts.map +1 -1
  49. package/dist/api/SpeechTranslation.js +28 -26
  50. package/dist/api/SpeechTranslation.js.map +1 -1
  51. package/dist/api/Synthesis.d.ts +13 -8
  52. package/dist/api/Synthesis.d.ts.map +1 -1
  53. package/dist/api/Synthesis.js +67 -89
  54. package/dist/api/Synthesis.js.map +1 -1
  55. package/dist/api/TextLanguageDetection.d.ts +4 -2
  56. package/dist/api/TextLanguageDetection.d.ts.map +1 -1
  57. package/dist/api/TextLanguageDetection.js +4 -7
  58. package/dist/api/TextLanguageDetection.js.map +1 -1
  59. package/dist/api/TextTranslation.d.ts +4 -2
  60. package/dist/api/TextTranslation.d.ts.map +1 -1
  61. package/dist/api/TextTranslation.js +13 -24
  62. package/dist/api/TextTranslation.js.map +1 -1
  63. package/dist/api/TimelineTranslationAlignment.d.ts +6 -3
  64. package/dist/api/TimelineTranslationAlignment.d.ts.map +1 -1
  65. package/dist/api/TimelineTranslationAlignment.js +20 -11
  66. package/dist/api/TimelineTranslationAlignment.js.map +1 -1
  67. package/dist/api/TranscriptAndTranslationAlignment.d.ts +6 -4
  68. package/dist/api/TranscriptAndTranslationAlignment.d.ts.map +1 -1
  69. package/dist/api/TranscriptAndTranslationAlignment.js +11 -12
  70. package/dist/api/TranscriptAndTranslationAlignment.js.map +1 -1
  71. package/dist/api/TranslationAlignment.d.ts +6 -4
  72. package/dist/api/TranslationAlignment.d.ts.map +1 -1
  73. package/dist/api/TranslationAlignment.js +20 -21
  74. package/dist/api/TranslationAlignment.js.map +1 -1
  75. package/dist/api/VoiceActivityDetection.d.ts +9 -8
  76. package/dist/api/VoiceActivityDetection.d.ts.map +1 -1
  77. package/dist/api/VoiceActivityDetection.js +20 -43
  78. package/dist/api/VoiceActivityDetection.js.map +1 -1
  79. package/dist/audio/AudioBufferConversion.js.map +1 -1
  80. package/dist/audio/AudioPlayer.d.ts +1 -3
  81. package/dist/audio/AudioPlayer.d.ts.map +1 -1
  82. package/dist/audio/AudioPlayer.js +3 -188
  83. package/dist/audio/AudioPlayer.js.map +1 -1
  84. package/dist/audio/AudioUtilities.d.ts +2 -1
  85. package/dist/audio/AudioUtilities.d.ts.map +1 -1
  86. package/dist/audio/AudioUtilities.js +2 -2
  87. package/dist/audio/AudioUtilities.js.map +1 -1
  88. package/dist/build-tools/MakeTarballsForInstalledPackages.js +3 -3
  89. package/dist/build-tools/MakeTarballsForInstalledPackages.js.map +1 -1
  90. package/dist/cli/CLI.d.ts.map +1 -1
  91. package/dist/cli/CLI.js +139 -92
  92. package/dist/cli/CLI.js.map +1 -1
  93. package/dist/codecs/FFMpegTranscoder.d.ts +4 -3
  94. package/dist/codecs/FFMpegTranscoder.d.ts.map +1 -1
  95. package/dist/codecs/FFMpegTranscoder.js +16 -14
  96. package/dist/codecs/FFMpegTranscoder.js.map +1 -1
  97. package/dist/codecs/TIMITCodec.d.ts.map +1 -1
  98. package/dist/data-structures/DynamicTypedArray.d.ts.map +1 -1
  99. package/dist/data-structures/DynamicTypedArray.js.map +1 -1
  100. package/dist/data-structures/Queue.d.ts.map +1 -1
  101. package/dist/data-structures/WindowedList.d.ts.map +1 -1
  102. package/dist/data-structures/WindowedList.js.map +1 -1
  103. package/dist/denoising/NSNet2.d.ts +3 -2
  104. package/dist/denoising/NSNet2.d.ts.map +1 -1
  105. package/dist/denoising/NSNet2.js +4 -4
  106. package/dist/denoising/NSNet2.js.map +1 -1
  107. package/dist/denoising/RNNoise.d.ts +2 -1
  108. package/dist/denoising/RNNoise.d.ts.map +1 -1
  109. package/dist/denoising/RNNoise.js +10 -6
  110. package/dist/denoising/RNNoise.js.map +1 -1
  111. package/dist/dsp/BiquadFilter.d.ts.map +1 -1
  112. package/dist/dsp/DecayingPeakEstimator.d.ts.map +1 -1
  113. package/dist/dsp/DecayingPeakEstimator.js.map +1 -1
  114. package/dist/dsp/FFT.d.ts.map +1 -1
  115. package/dist/dsp/FFT.js +2 -1
  116. package/dist/dsp/FFT.js.map +1 -1
  117. package/dist/dsp/KWeightingFilter.d.ts.map +1 -1
  118. package/dist/dsp/KWeightingFilter.js.map +1 -1
  119. package/dist/dsp/LoudnessEstimator.d.ts.map +1 -1
  120. package/dist/dsp/LoudnessEstimator.js.map +1 -1
  121. package/dist/dsp/MFCC.d.ts +3 -2
  122. package/dist/dsp/MFCC.d.ts.map +1 -1
  123. package/dist/dsp/MFCC.js +4 -4
  124. package/dist/dsp/MFCC.js.map +1 -1
  125. package/dist/dsp/MelSpectrogram.d.ts +10 -8
  126. package/dist/dsp/MelSpectrogram.d.ts.map +1 -1
  127. package/dist/dsp/MelSpectrogram.js +31 -34
  128. package/dist/dsp/MelSpectrogram.js.map +1 -1
  129. package/dist/dsp/Rubberband.d.ts.map +1 -1
  130. package/dist/dsp/Rubberband.js +8 -3
  131. package/dist/dsp/Rubberband.js.map +1 -1
  132. package/dist/dsp/Sonic.d.ts.map +1 -1
  133. package/dist/dsp/Sonic.js +1 -1
  134. package/dist/dsp/Sonic.js.map +1 -1
  135. package/dist/dsp/SpeexResampler.d.ts.map +1 -1
  136. package/dist/dsp/SpeexResampler.js +1 -1
  137. package/dist/dsp/SpeexResampler.js.map +1 -1
  138. package/dist/encodings/Ascii.d.ts +1 -1
  139. package/dist/encodings/Ascii.d.ts.map +1 -1
  140. package/dist/encodings/Base64.js.map +1 -1
  141. package/dist/encodings/Utf16.d.ts.map +1 -1
  142. package/dist/encodings/Utf8.d.ts.map +1 -1
  143. package/dist/math/VectorMath.d.ts +1 -0
  144. package/dist/math/VectorMath.d.ts.map +1 -1
  145. package/dist/math/VectorMath.js +9 -5
  146. package/dist/math/VectorMath.js.map +1 -1
  147. package/dist/nlp/ChineseSegmentation.d.ts +1 -1
  148. package/dist/nlp/ChineseSegmentation.d.ts.map +1 -1
  149. package/dist/nlp/EspeakPhonemizer.d.ts +1 -1
  150. package/dist/nlp/EspeakPhonemizer.d.ts.map +1 -1
  151. package/dist/nlp/EspeakPhonemizer.js +2 -2
  152. package/dist/nlp/EspeakPhonemizer.js.map +1 -1
  153. package/dist/nlp/IPA.d.ts +2 -2
  154. package/dist/nlp/Segmentation.d.ts +1 -1
  155. package/dist/nlp/Segmentation.d.ts.map +1 -1
  156. package/dist/nlp/Segmentation.js +8 -4
  157. package/dist/nlp/Segmentation.js.map +1 -1
  158. package/dist/recognition/AmazonTranscribeSTT.d.ts +2 -1
  159. package/dist/recognition/AmazonTranscribeSTT.d.ts.map +1 -1
  160. package/dist/recognition/AmazonTranscribeSTT.js +3 -3
  161. package/dist/recognition/AmazonTranscribeSTT.js.map +1 -1
  162. package/dist/recognition/AzureCognitiveServicesSTT.d.ts +2 -1
  163. package/dist/recognition/AzureCognitiveServicesSTT.d.ts.map +1 -1
  164. package/dist/recognition/AzureCognitiveServicesSTT.js +4 -4
  165. package/dist/recognition/AzureCognitiveServicesSTT.js.map +1 -1
  166. package/dist/recognition/DeepgramSTT.d.ts +2 -1
  167. package/dist/recognition/DeepgramSTT.d.ts.map +1 -1
  168. package/dist/recognition/DeepgramSTT.js +12 -13
  169. package/dist/recognition/DeepgramSTT.js.map +1 -1
  170. package/dist/recognition/GoogleCloudSTT.d.ts +2 -1
  171. package/dist/recognition/GoogleCloudSTT.d.ts.map +1 -1
  172. package/dist/recognition/GoogleCloudSTT.js +11 -10
  173. package/dist/recognition/GoogleCloudSTT.js.map +1 -1
  174. package/dist/recognition/OpenAICloudSTT.d.ts +2 -1
  175. package/dist/recognition/OpenAICloudSTT.d.ts.map +1 -1
  176. package/dist/recognition/OpenAICloudSTT.js +6 -6
  177. package/dist/recognition/OpenAICloudSTT.js.map +1 -1
  178. package/dist/recognition/WhisperCommon.d.ts +9 -0
  179. package/dist/recognition/WhisperCommon.d.ts.map +1 -0
  180. package/dist/recognition/WhisperCommon.js +52 -0
  181. package/dist/recognition/WhisperCommon.js.map +1 -0
  182. package/dist/recognition/{WhisperCppSTT.d.ts → WhisperCppCliSTT.d.ts} +14 -16
  183. package/dist/recognition/WhisperCppCliSTT.d.ts.map +1 -0
  184. package/dist/recognition/{WhisperCppSTT.js → WhisperCppCliSTT.js} +55 -84
  185. package/dist/recognition/WhisperCppCliSTT.js.map +1 -0
  186. package/dist/recognition/WhisperSTT.d.ts +72 -85
  187. package/dist/recognition/WhisperSTT.d.ts.map +1 -1
  188. package/dist/recognition/WhisperSTT.js +384 -519
  189. package/dist/recognition/WhisperSTT.js.map +1 -1
  190. package/dist/server/Client.d.ts +2 -2
  191. package/dist/server/Client.d.ts.map +1 -1
  192. package/dist/server/Client.js.map +1 -1
  193. package/dist/server/Worker.d.ts +6 -7
  194. package/dist/server/Worker.d.ts.map +1 -1
  195. package/dist/server/Worker.js +42 -44
  196. package/dist/server/Worker.js.map +1 -1
  197. package/dist/source-separation/MDXNetSourceSeparation.d.ts +3 -2
  198. package/dist/source-separation/MDXNetSourceSeparation.d.ts.map +1 -1
  199. package/dist/source-separation/MDXNetSourceSeparation.js +10 -8
  200. package/dist/source-separation/MDXNetSourceSeparation.js.map +1 -1
  201. package/dist/speech-embeddings/WavToVec2BertFeatureEmbeddings.d.ts +3 -2
  202. package/dist/speech-embeddings/WavToVec2BertFeatureEmbeddings.d.ts.map +1 -1
  203. package/dist/speech-embeddings/WavToVec2BertFeatureEmbeddings.js +5 -5
  204. package/dist/speech-embeddings/WavToVec2BertFeatureEmbeddings.js.map +1 -1
  205. package/dist/speech-language-detection/SileroLanguageDetection.d.ts +5 -3
  206. package/dist/speech-language-detection/SileroLanguageDetection.d.ts.map +1 -1
  207. package/dist/speech-language-detection/SileroLanguageDetection.js +8 -8
  208. package/dist/speech-language-detection/SileroLanguageDetection.js.map +1 -1
  209. package/dist/speech-search/DTWSpeechSearch.d.ts +2 -1
  210. package/dist/speech-search/DTWSpeechSearch.d.ts.map +1 -1
  211. package/dist/speech-search/DTWSpeechSearch.js +4 -4
  212. package/dist/speech-search/DTWSpeechSearch.js.map +1 -1
  213. package/dist/subtitles/Subtitles.d.ts +13 -1
  214. package/dist/subtitles/Subtitles.d.ts.map +1 -1
  215. package/dist/subtitles/Subtitles.js +22 -22
  216. package/dist/subtitles/Subtitles.js.map +1 -1
  217. package/dist/synthesis/AwsPollyTTS.d.ts +3 -2
  218. package/dist/synthesis/AwsPollyTTS.d.ts.map +1 -1
  219. package/dist/synthesis/AwsPollyTTS.js +5 -5
  220. package/dist/synthesis/AwsPollyTTS.js.map +1 -1
  221. package/dist/synthesis/AzureCognitiveServicesTTS.d.ts +2 -1
  222. package/dist/synthesis/AzureCognitiveServicesTTS.d.ts.map +1 -1
  223. package/dist/synthesis/AzureCognitiveServicesTTS.js +3 -3
  224. package/dist/synthesis/AzureCognitiveServicesTTS.js.map +1 -1
  225. package/dist/synthesis/CoquiServerTTS.d.ts +2 -1
  226. package/dist/synthesis/CoquiServerTTS.d.ts.map +1 -1
  227. package/dist/synthesis/CoquiServerTTS.js +7 -8
  228. package/dist/synthesis/CoquiServerTTS.js.map +1 -1
  229. package/dist/synthesis/DeepgramTTS.d.ts +2 -2
  230. package/dist/synthesis/DeepgramTTS.d.ts.map +1 -1
  231. package/dist/synthesis/DeepgramTTS.js +13 -13
  232. package/dist/synthesis/DeepgramTTS.js.map +1 -1
  233. package/dist/synthesis/ElevenLabsTTS.d.ts +3 -3
  234. package/dist/synthesis/ElevenLabsTTS.d.ts.map +1 -1
  235. package/dist/synthesis/ElevenLabsTTS.js +22 -21
  236. package/dist/synthesis/ElevenLabsTTS.js.map +1 -1
  237. package/dist/synthesis/EspeakTTS.d.ts +11 -9
  238. package/dist/synthesis/EspeakTTS.d.ts.map +1 -1
  239. package/dist/synthesis/EspeakTTS.js +118 -68
  240. package/dist/synthesis/EspeakTTS.js.map +1 -1
  241. package/dist/synthesis/FliteTTS.d.ts +2 -2
  242. package/dist/synthesis/FliteTTS.d.ts.map +1 -1
  243. package/dist/synthesis/FliteTTS.js +2 -2
  244. package/dist/synthesis/FliteTTS.js.map +1 -1
  245. package/dist/synthesis/GnuSpeechTTS.d.ts +2 -2
  246. package/dist/synthesis/GnuSpeechTTS.d.ts.map +1 -1
  247. package/dist/synthesis/GnuSpeechTTS.js +1 -1
  248. package/dist/synthesis/GnuSpeechTTS.js.map +1 -1
  249. package/dist/synthesis/GoogleCloudTTS.d.ts +3 -2
  250. package/dist/synthesis/GoogleCloudTTS.d.ts.map +1 -1
  251. package/dist/synthesis/GoogleCloudTTS.js +15 -14
  252. package/dist/synthesis/GoogleCloudTTS.js.map +1 -1
  253. package/dist/synthesis/GoogleTranslateTTS.d.ts +3 -2
  254. package/dist/synthesis/GoogleTranslateTTS.d.ts.map +1 -1
  255. package/dist/synthesis/GoogleTranslateTTS.js +11 -11
  256. package/dist/synthesis/GoogleTranslateTTS.js.map +1 -1
  257. package/dist/synthesis/KokoroTTS.d.ts +4 -4
  258. package/dist/synthesis/KokoroTTS.d.ts.map +1 -1
  259. package/dist/synthesis/KokoroTTS.js +11 -10
  260. package/dist/synthesis/KokoroTTS.js.map +1 -1
  261. package/dist/synthesis/MicrosoftEdgeTTS.d.ts +4 -3
  262. package/dist/synthesis/MicrosoftEdgeTTS.d.ts.map +1 -1
  263. package/dist/synthesis/MicrosoftEdgeTTS.js +41 -20
  264. package/dist/synthesis/MicrosoftEdgeTTS.js.map +1 -1
  265. package/dist/synthesis/OpenAICloudTTS.d.ts +2 -2
  266. package/dist/synthesis/OpenAICloudTTS.d.ts.map +1 -1
  267. package/dist/synthesis/OpenAICloudTTS.js +6 -5
  268. package/dist/synthesis/OpenAICloudTTS.js.map +1 -1
  269. package/dist/synthesis/SamTTS.d.ts +2 -1
  270. package/dist/synthesis/SamTTS.d.ts.map +1 -1
  271. package/dist/synthesis/SamTTS.js +2 -2
  272. package/dist/synthesis/SamTTS.js.map +1 -1
  273. package/dist/synthesis/SapiTTS.d.ts +2 -2
  274. package/dist/synthesis/SapiTTS.d.ts.map +1 -1
  275. package/dist/synthesis/SapiTTS.js +2 -2
  276. package/dist/synthesis/SapiTTS.js.map +1 -1
  277. package/dist/synthesis/SvoxPicoTTS.d.ts +2 -2
  278. package/dist/synthesis/SvoxPicoTTS.d.ts.map +1 -1
  279. package/dist/synthesis/SvoxPicoTTS.js +3 -3
  280. package/dist/synthesis/SvoxPicoTTS.js.map +1 -1
  281. package/dist/synthesis/VitsTTS.d.ts +3 -3
  282. package/dist/synthesis/VitsTTS.d.ts.map +1 -1
  283. package/dist/synthesis/VitsTTS.js +14 -11
  284. package/dist/synthesis/VitsTTS.js.map +1 -1
  285. package/dist/text-translation/DeepLTextTranslation.d.ts +2 -2
  286. package/dist/text-translation/DeepLTextTranslation.d.ts.map +1 -1
  287. package/dist/text-translation/DeepLTextTranslation.js +10 -9
  288. package/dist/text-translation/DeepLTextTranslation.js.map +1 -1
  289. package/dist/text-translation/GoogleTranslateTextTranslation.d.ts +4 -4
  290. package/dist/text-translation/GoogleTranslateTextTranslation.d.ts.map +1 -1
  291. package/dist/text-translation/GoogleTranslateTextTranslation.js +20 -18
  292. package/dist/text-translation/GoogleTranslateTextTranslation.js.map +1 -1
  293. package/dist/text-translation/NLLBTextTranslation.d.ts +2 -2
  294. package/dist/text-translation/NLLBTextTranslation.d.ts.map +1 -1
  295. package/dist/text-translation/NLLBTextTranslation.js +4 -6
  296. package/dist/text-translation/NLLBTextTranslation.js.map +1 -1
  297. package/dist/typings/TypedArray.d.ts.map +1 -1
  298. package/dist/utilities/Compression.d.ts +4 -3
  299. package/dist/utilities/Compression.d.ts.map +1 -1
  300. package/dist/utilities/Compression.js +9 -9
  301. package/dist/utilities/Compression.js.map +1 -1
  302. package/dist/utilities/FileDownloader.d.ts +6 -3
  303. package/dist/utilities/FileDownloader.d.ts.map +1 -1
  304. package/dist/utilities/FileDownloader.js +25 -21
  305. package/dist/utilities/FileDownloader.js.map +1 -1
  306. package/dist/utilities/FileReader.d.ts.map +1 -1
  307. package/dist/utilities/FileReader.js.map +1 -1
  308. package/dist/utilities/FileSystem.js +1 -1
  309. package/dist/utilities/FileSystem.js.map +1 -1
  310. package/dist/utilities/FileWriter.d.ts.map +1 -1
  311. package/dist/utilities/FileWriter.js.map +1 -1
  312. package/dist/utilities/Hashing.d.ts.map +1 -1
  313. package/dist/utilities/Hashing.js.map +1 -1
  314. package/dist/utilities/Locale.js.map +1 -1
  315. package/dist/utilities/Logger.d.ts +17 -9
  316. package/dist/utilities/Logger.d.ts.map +1 -1
  317. package/dist/utilities/Logger.js +50 -35
  318. package/dist/utilities/Logger.js.map +1 -1
  319. package/dist/utilities/NpmUtilities.d.ts.map +1 -1
  320. package/dist/utilities/NpmUtilities.js +4 -5
  321. package/dist/utilities/NpmUtilities.js.map +1 -1
  322. package/dist/utilities/ObjectUtilities.js.map +1 -1
  323. package/dist/utilities/OpenPromise.d.ts.map +1 -1
  324. package/dist/utilities/OpenPromise.js.map +1 -1
  325. package/dist/utilities/PackageManager.d.ts +4 -1
  326. package/dist/utilities/PackageManager.d.ts.map +1 -1
  327. package/dist/utilities/PackageManager.js +37 -22
  328. package/dist/utilities/PackageManager.js.map +1 -1
  329. package/dist/utilities/PathUtilities.d.ts +2 -0
  330. package/dist/utilities/PathUtilities.d.ts.map +1 -1
  331. package/dist/utilities/PathUtilities.js +5 -2
  332. package/dist/utilities/PathUtilities.js.map +1 -1
  333. package/dist/utilities/RandomGenerator.d.ts.map +1 -1
  334. package/dist/utilities/SignalChannel.d.ts.map +1 -1
  335. package/dist/utilities/SmoothEstimator.d.ts.map +1 -1
  336. package/dist/utilities/SmoothEstimator.js.map +1 -1
  337. package/dist/utilities/StringBuilder.d.ts.map +1 -1
  338. package/dist/utilities/TarballMaker.d.ts +4 -3
  339. package/dist/utilities/TarballMaker.d.ts.map +1 -1
  340. package/dist/utilities/TarballMaker.js +6 -6
  341. package/dist/utilities/TarballMaker.js.map +1 -1
  342. package/dist/utilities/Timeline.js.map +1 -1
  343. package/dist/utilities/Timer.d.ts.map +1 -1
  344. package/dist/utilities/Utilities.d.ts +9 -7
  345. package/dist/utilities/Utilities.d.ts.map +1 -1
  346. package/dist/utilities/Utilities.js +49 -33
  347. package/dist/utilities/Utilities.js.map +1 -1
  348. package/dist/utilities/VirtualFileReadStream.d.ts.map +1 -1
  349. package/dist/utilities/WebReader.d.ts +2 -1
  350. package/dist/utilities/WebReader.d.ts.map +1 -1
  351. package/dist/utilities/WebReader.js +7 -6
  352. package/dist/utilities/WebReader.js.map +1 -1
  353. package/dist/utilities/WikipediaReader.d.ts +2 -1
  354. package/dist/utilities/WikipediaReader.d.ts.map +1 -1
  355. package/dist/utilities/WikipediaReader.js +1 -5
  356. package/dist/utilities/WikipediaReader.js.map +1 -1
  357. package/dist/voice-activity-detection/AdaptiveGateVAD.d.ts +2 -1
  358. package/dist/voice-activity-detection/AdaptiveGateVAD.d.ts.map +1 -1
  359. package/dist/voice-activity-detection/AdaptiveGateVAD.js +1 -1
  360. package/dist/voice-activity-detection/AdaptiveGateVAD.js.map +1 -1
  361. package/dist/voice-activity-detection/SileroVAD.d.ts.map +1 -1
  362. package/dist/voice-activity-detection/SileroVAD.js.map +1 -1
  363. package/dist/voice-activity-detection/WebRtcVAD.d.ts.map +1 -1
  364. package/dist/voice-activity-detection/WebRtcVAD.js +1 -1
  365. package/dist/voice-activity-detection/WebRtcVAD.js.map +1 -1
  366. package/docs/API.md +62 -17
  367. package/docs/CUDA.md +4 -3
  368. package/docs/Engines.md +8 -7
  369. package/docs/Licenses.md +0 -3
  370. package/docs/Options.md +27 -31
  371. package/docs/Server.md +1 -0
  372. package/docs/Tasklist.md +2 -1
  373. package/docs/Technical.md +2 -2
  374. package/package.json +45 -35
  375. package/src/alignment/SemanticTextAlignment.ts +14 -7
  376. package/src/alignment/SpeechAlignment.ts +47 -150
  377. package/src/api/APIOptions.ts +1 -1
  378. package/src/api/Alignment.ts +95 -61
  379. package/src/api/Common.ts +11 -0
  380. package/src/api/Denoising.ts +22 -17
  381. package/src/api/GlobalOptions.ts +4 -20
  382. package/src/api/Recognition.ts +106 -123
  383. package/src/api/SourceSeparation.ts +39 -21
  384. package/src/api/SpeechLanguageDetection.ts +77 -37
  385. package/src/api/SpeechSearch.ts +6 -1
  386. package/src/api/SpeechTranslation.ts +75 -38
  387. package/src/api/Synthesis.ts +220 -116
  388. package/src/api/TextLanguageDetection.ts +10 -12
  389. package/src/api/TextTranslation.ts +43 -26
  390. package/src/api/TimelineTranslationAlignment.ts +41 -13
  391. package/src/api/TranscriptAndTranslationAlignment.ts +28 -15
  392. package/src/api/TranslationAlignment.ts +53 -24
  393. package/src/api/VoiceActivityDetection.ts +33 -68
  394. package/src/audio/AudioPlayer.ts +4 -232
  395. package/src/audio/AudioUtilities.ts +9 -2
  396. package/src/build-tools/MakeTarballsForInstalledPackages.ts +4 -3
  397. package/src/cli/CLI.ts +209 -101
  398. package/src/codecs/FFMpegTranscoder.ts +18 -16
  399. package/src/denoising/NSNet2.ts +5 -4
  400. package/src/denoising/RNNoise.ts +14 -6
  401. package/src/dsp/FFT.ts +2 -1
  402. package/src/dsp/MFCC.ts +7 -5
  403. package/src/dsp/MelSpectrogram.ts +56 -36
  404. package/src/dsp/Rubberband.ts +10 -3
  405. package/src/dsp/Sonic.ts +2 -1
  406. package/src/dsp/SpeexResampler.ts +2 -1
  407. package/src/encodings/Ascii.ts +1 -1
  408. package/src/encodings/Base64.ts +1 -1
  409. package/src/math/VectorMath.ts +10 -6
  410. package/src/nlp/EspeakPhonemizer.ts +2 -2
  411. package/src/nlp/Segmentation.ts +9 -4
  412. package/src/recognition/AmazonTranscribeSTT.ts +4 -3
  413. package/src/recognition/AzureCognitiveServicesSTT.ts +5 -4
  414. package/src/recognition/DeepgramSTT.ts +16 -16
  415. package/src/recognition/GoogleCloudSTT.ts +14 -12
  416. package/src/recognition/OpenAICloudSTT.ts +12 -6
  417. package/src/recognition/WhisperCommon.ts +130 -0
  418. package/src/recognition/{WhisperCppSTT.ts → WhisperCppCliSTT.ts} +73 -133
  419. package/src/recognition/WhisperSTT.ts +569 -718
  420. package/src/server/Client.ts +4 -4
  421. package/src/server/Worker.ts +59 -59
  422. package/src/source-separation/MDXNetSourceSeparation.ts +15 -10
  423. package/src/speech-embeddings/WavToVec2BertFeatureEmbeddings.ts +7 -5
  424. package/src/speech-language-detection/SileroLanguageDetection.ts +18 -9
  425. package/src/speech-search/DTWSpeechSearch.ts +6 -5
  426. package/src/subtitles/Subtitles.ts +22 -22
  427. package/src/synthesis/AwsPollyTTS.ts +12 -5
  428. package/src/synthesis/AzureCognitiveServicesTTS.ts +11 -3
  429. package/src/synthesis/CoquiServerTTS.ts +8 -7
  430. package/src/synthesis/DeepgramTTS.ts +21 -15
  431. package/src/synthesis/ElevenLabsTTS.ts +33 -23
  432. package/src/synthesis/EspeakTTS.ts +145 -69
  433. package/src/synthesis/FliteTTS.ts +3 -3
  434. package/src/synthesis/GnuSpeechTTS.ts +2 -2
  435. package/src/synthesis/GoogleCloudTTS.ts +23 -14
  436. package/src/synthesis/GoogleTranslateTTS.ts +19 -11
  437. package/src/synthesis/KokoroTTS.ts +37 -14
  438. package/src/synthesis/MicrosoftEdgeTTS.ts +71 -23
  439. package/src/synthesis/OpenAICloudTTS.ts +7 -6
  440. package/src/synthesis/SamTTS.ts +3 -2
  441. package/src/synthesis/SapiTTS.ts +3 -3
  442. package/src/synthesis/SvoxPicoTTS.ts +4 -5
  443. package/src/synthesis/VitsTTS.ts +43 -15
  444. package/src/text-translation/DeepLTextTranslation.ts +12 -10
  445. package/src/text-translation/GoogleTranslateTextTranslation.ts +35 -21
  446. package/src/text-translation/NLLBTextTranslation.ts +5 -9
  447. package/src/typings/Fillers.d.ts +0 -60
  448. package/src/typings/TypedArray.ts +12 -1
  449. package/src/utilities/Compression.ts +10 -9
  450. package/src/utilities/FileDownloader.ts +38 -23
  451. package/src/utilities/FileSystem.ts +1 -1
  452. package/src/utilities/Logger.ts +59 -42
  453. package/src/utilities/NpmUtilities.ts +4 -6
  454. package/src/utilities/OpenPromise.ts +1 -2
  455. package/src/utilities/PackageManager.ts +53 -26
  456. package/src/utilities/PathUtilities.ts +6 -2
  457. package/src/utilities/TarballMaker.ts +7 -7
  458. package/src/utilities/Utilities.ts +58 -41
  459. package/src/utilities/WebReader.ts +11 -6
  460. package/src/utilities/WikipediaReader.ts +2 -8
  461. package/src/voice-activity-detection/AdaptiveGateVAD.ts +13 -8
  462. package/src/voice-activity-detection/WebRtcVAD.ts +1 -2
  463. package/tsconfig.json +53 -54
  464. package/dist/audio/AudioRecorder.d.ts +0 -4
  465. package/dist/audio/AudioRecorder.d.ts.map +0 -1
  466. package/dist/audio/AudioRecorder.js +0 -68
  467. package/dist/audio/AudioRecorder.js.map +0 -1
  468. package/dist/audio/SoxPath.d.ts +0 -2
  469. package/dist/audio/SoxPath.d.ts.map +0 -1
  470. package/dist/audio/SoxPath.js +0 -24
  471. package/dist/audio/SoxPath.js.map +0 -1
  472. package/dist/recognition/SileroSTT.d.ts +0 -30
  473. package/dist/recognition/SileroSTT.d.ts.map +0 -1
  474. package/dist/recognition/SileroSTT.js +0 -152
  475. package/dist/recognition/SileroSTT.js.map +0 -1
  476. package/dist/recognition/VoskSTT.d.ts +0 -11
  477. package/dist/recognition/VoskSTT.d.ts.map +0 -1
  478. package/dist/recognition/VoskSTT.js +0 -72
  479. package/dist/recognition/VoskSTT.js.map +0 -1
  480. package/dist/recognition/WhisperCppSTT.d.ts.map +0 -1
  481. package/dist/recognition/WhisperCppSTT.js.map +0 -1
  482. package/dist/synthesis/StreamlabsPollyTTS.d.ts +0 -12
  483. package/dist/synthesis/StreamlabsPollyTTS.d.ts.map +0 -1
  484. package/dist/synthesis/StreamlabsPollyTTS.js +0 -88
  485. package/dist/synthesis/StreamlabsPollyTTS.js.map +0 -1
  486. package/dist/utilities/BinaryUtilities.d.ts +0 -14
  487. package/dist/utilities/BinaryUtilities.d.ts.map +0 -1
  488. package/dist/utilities/BinaryUtilities.js +0 -113
  489. package/dist/utilities/BinaryUtilities.js.map +0 -1
  490. package/src/audio/AudioRecorder.ts +0 -91
  491. package/src/audio/SoxPath.ts +0 -31
  492. package/src/recognition/SileroSTT.ts +0 -222
  493. package/src/recognition/VoskSTT.ts +0 -112
  494. package/src/synthesis/StreamlabsPollyTTS.ts +0 -114
  495. package/src/utilities/BinaryUtilities.ts +0 -138
  496. /package/{LICENSE.md → LICENSE.GPLv3.md} +0 -0
@@ -1,26 +1,25 @@
1
1
  import chalk from 'chalk';
2
+ import { getRawAudioDuration } from '../audio/AudioUtilities.js';
3
+ import { formatLanguageCodeWithName, getShortLanguageCode, languageCodeToName } from '../utilities/Locale.js';
2
4
  import { Logger } from '../utilities/Logger.js';
3
- import { computeMelSpectrogramUsingFilterbanks } from '../dsp/MelSpectrogram.js';
4
- import { clip, getIntegerRange, getTopKIndexes, splitFloat32Array, yieldToEventLoop } from '../utilities/Utilities.js';
5
- import { indexOfMax, logOfVector, logSumExp, meanOfVector, medianOfVector, softmax, sumAndSumOfSquaresOfVector } from '../math/VectorMath.js';
6
- import { alignDTWWindowed } from '../alignment/DTWSequenceAlignmentWindowed.js';
7
5
  import { extendDeep } from '../utilities/ObjectUtilities.js';
8
- import { getRawAudioDuration, sliceRawAudio } from '../audio/AudioUtilities.js';
9
- import { readFileAsUtf8 } from '../utilities/FileSystem.js';
10
- import { logLevelGreaterOrEqualTo } from '../api/API.js';
11
- import { formatLanguageCodeWithName, getShortLanguageCode, languageCodeToName } from '../utilities/Locale.js';
12
- import { loadPackage } from '../utilities/PackageManager.js';
13
6
  import { XorShift32PRNG } from '../utilities/RandomGenerator.js';
14
- import { detectSpeechLanguageByParts } from '../api/SpeechLanguageDetection.js';
15
- import { includesPunctuation, isWhitespace, splitToWords } from '../nlp/Segmentation.js';
16
- import { medianOf5Filter } from '../math/MedianFilter.js';
17
- import { getDeflateCompressionMetricsForString } from '../utilities/Compression.js';
18
- import { dmlProviderAvailable, getOnnxSessionOptions, makeOnnxLikeFloat32Tensor } from '../utilities/OnnxUtilities.js';
19
7
  import { murmurHash3_int32Input } from '../utilities/Hashing.js';
8
+ import { WhisperCppContext, WhisperAlignmentHeadsPreset, whisperModelIdToTextLayerCount, whisperModelIdToAlignmentHeadsPreset, GgmlLogLevel } from '@echogarden/whisper.cpp-binding';
9
+ import { getDeflateCompressionMetricsForString } from '../utilities/Compression.js';
10
+ import { indexOfMax, meanOfVector, medianOfVector, softmax, sumAndSumOfSquaresOfVector, sumVector } from '../math/VectorMath.js';
11
+ import { loadPackage } from '../utilities/PackageManager.js';
12
+ import { joinPath, resolvePath } from '../utilities/PathUtilities.js';
13
+ import { readFileAsUtf8 } from '../utilities/FileSystem.js';
14
+ import { clip, concatUint8Arrays, getIntegerRange, getTopKIndexes, yieldToEventLoop } from '../utilities/Utilities.js';
20
15
  import { containsInvalidCodepoint, getTokenRepetitionScore } from '../utilities/StringUtilities.js';
21
- import { joinPath } from '../utilities/PathUtilities.js';
16
+ import { alignDTWWindowed } from '../alignment/DTWSequenceAlignmentWindowed.js';
17
+ import { medianOf5Filter } from '../math/MedianFilter.js';
18
+ import { includesPunctuation, isAllWhitespace, splitToWords } from '../nlp/Segmentation.js';
22
19
  import { Timer } from '../utilities/Timer.js';
23
- export async function recognize(sourceRawAudio, modelName, modelDir, task, sourceLanguage, options, onPart) {
20
+ import { computeMelSpectrogramUsingFilterbank } from '../dsp/MelSpectrogram.js';
21
+ import { detectSpeechLanguageByParts } from '../api/SpeechLanguageDetection.js';
22
+ export async function recognize(sourceRawAudio, modelId, modelPath, libPath, task, sourceLanguage, options, callbacks) {
24
23
  options = extendDeep(defaultWhisperOptions, options);
25
24
  if (sourceRawAudio.sampleRate !== 16000) {
26
25
  throw new Error('Source audio must have a sample rate of 16000 Hz');
@@ -29,10 +28,10 @@ export async function recognize(sourceRawAudio, modelName, modelDir, task, sourc
29
28
  if (!(sourceLanguage in languageIdLookup)) {
30
29
  throw new Error(`The language ${formatLanguageCodeWithName(sourceLanguage)} is not supported by the Whisper engine.`);
31
30
  }
32
- if (isEnglishOnlyModel(modelName) && sourceLanguage !== 'en') {
33
- throw new Error(`The model '${modelName}' can only be used with English inputs. However, the given source language was ${languageCodeToName(sourceLanguage)}.`);
31
+ if (isEnglishOnlyModel(modelId) && sourceLanguage !== 'en') {
32
+ throw new Error(`The model '${modelId}' can only be used with English inputs. However, the given source language was ${languageCodeToName(sourceLanguage)}.`);
34
33
  }
35
- if (modelName === 'large-v3-turbo' && task === 'translate') {
34
+ if (modelId === 'large-v3-turbo' && task === 'translate') {
36
35
  throw new Error(`The 'large-v3-turbo' model doesn't support translation tasks.`);
37
36
  }
38
37
  if (options.temperature && options.temperature < 0) {
@@ -40,19 +39,15 @@ export async function recognize(sourceRawAudio, modelName, modelDir, task, sourc
40
39
  }
41
40
  // Workaround issue with large-v3-turbo that produces invalid results when a prompt is passed to it.
42
41
  // Always disable autoprompting for that model.
43
- if (options.autoPromptParts && modelName === 'large-v3-turbo') {
42
+ if (options.autoPromptParts && modelId === 'large-v3-turbo') {
44
43
  options.autoPromptParts = false;
45
44
  }
46
- // Select encoder ONNX provider
47
- const encoderProviders = options.encoderProvider ? [options.encoderProvider] : getDefaultEncoderProvidersForModel(modelName);
48
- // Select decoder ONNX provider
49
- const decoderProviders = options.decoderProvider ? [options.decoderProvider] : getDefaultDecoderProvidersForModel(modelName);
50
45
  const seed = options.seed;
51
- const whisper = new Whisper(modelName, modelDir, encoderProviders, decoderProviders, seed);
52
- const result = await whisper.recognize(sourceRawAudio, task, sourceLanguage, options, undefined, onPart);
46
+ const whisper = new Whisper(modelId, modelPath, libPath, seed);
47
+ const result = await whisper.recognize(sourceRawAudio, task, sourceLanguage, options, undefined, callbacks);
53
48
  return result;
54
49
  }
55
- export async function align(sourceRawAudio, transcript, modelName, modelDir, sourceLanguage, options) {
50
+ export async function align(sourceRawAudio, transcript, modelId, modelPath, libPath, sourceLanguage, options, callbacks) {
56
51
  options = extendDeep(defaultWhisperAlignmentOptions, options);
57
52
  if (sourceRawAudio.sampleRate !== 16000) {
58
53
  throw new Error('Source audio must have a sample rate of 16000 Hz');
@@ -61,18 +56,14 @@ export async function align(sourceRawAudio, transcript, modelName, modelDir, sou
61
56
  if (!(sourceLanguage in languageIdLookup)) {
62
57
  throw new Error(`The language ${formatLanguageCodeWithName(sourceLanguage)} is not supported by the Whisper engine.`);
63
58
  }
64
- if (isEnglishOnlyModel(modelName) && sourceLanguage !== 'en') {
65
- throw new Error(`The model '${modelName}' can only be used with English inputs. However, the given source language was ${languageCodeToName(sourceLanguage)}.`);
59
+ if (isEnglishOnlyModel(modelId) && sourceLanguage !== 'en') {
60
+ throw new Error(`The model '${modelId}' can only be used with English inputs. However, the given source language was ${languageCodeToName(sourceLanguage)}.`);
66
61
  }
67
- // Select encoder ONNX provider
68
- const encoderProviders = options.encoderProvider ? [options.encoderProvider] : getDefaultEncoderProvidersForModel(modelName);
69
- // Select decoder ONNX provider
70
- const decoderProviders = options.decoderProvider ? [options.decoderProvider] : getDefaultDecoderProvidersForModel(modelName);
71
- const whisper = new Whisper(modelName, modelDir, encoderProviders, decoderProviders);
72
- const timeline = await whisper.align(sourceRawAudio, transcript, sourceLanguage, 'transcribe', options);
62
+ const whisper = new Whisper(modelId, modelPath, libPath);
63
+ const timeline = await whisper.align(sourceRawAudio, transcript, sourceLanguage, 'transcribe', options, callbacks);
73
64
  return timeline;
74
65
  }
75
- export async function alignEnglishTranslation(sourceRawAudio, translatedTranscript, modelName, modelDir, sourceLanguage, options) {
66
+ export async function alignEnglishTranslation(sourceRawAudio, translatedTranscript, modelId, modelPath, libPath, sourceLanguage, options, callbacks) {
76
67
  options = extendDeep(defaultWhisperAlignmentOptions, options);
77
68
  if (sourceRawAudio.sampleRate !== 16000) {
78
69
  throw new Error('Source audio must have a sample rate of 16000 Hz');
@@ -81,133 +72,58 @@ export async function alignEnglishTranslation(sourceRawAudio, translatedTranscri
81
72
  if (!(sourceLanguage in languageIdLookup)) {
82
73
  throw new Error(`The source language ${formatLanguageCodeWithName(sourceLanguage)} is not supported by the Whisper engine.`);
83
74
  }
84
- if (modelName === 'large-v3-turbo') {
75
+ if (modelId === 'large-v3-turbo') {
85
76
  throw new Error(`The 'large-v3-turbo' model doesn't support translation tasks, so cannot be used for translation alignment.`);
86
77
  }
87
- if (isEnglishOnlyModel(modelName)) {
78
+ if (isEnglishOnlyModel(modelId)) {
88
79
  throw new Error(`Translation alignment can only be done with multilingual models.`);
89
80
  }
90
- // Select encoder ONNX provider
91
- const encoderProviders = options.encoderProvider ? [options.encoderProvider] : getDefaultEncoderProvidersForModel(modelName);
92
- // Select decoder ONNX provider
93
- const decoderProviders = options.decoderProvider ? [options.decoderProvider] : getDefaultDecoderProvidersForModel(modelName);
94
- const whisper = new Whisper(modelName, modelDir, encoderProviders, decoderProviders);
95
- const timeline = await whisper.align(sourceRawAudio, translatedTranscript, sourceLanguage, 'translate', options);
81
+ const whisper = new Whisper(modelId, modelPath, libPath);
82
+ const timeline = await whisper.align(sourceRawAudio, translatedTranscript, sourceLanguage, 'translate', options, callbacks);
96
83
  return timeline;
97
84
  }
98
- export async function detectLanguage(sourceRawAudio, modelName, modelDir, options) {
85
+ export async function detectLanguage(sourceRawAudio, modelId, modelPath, libPath, options, callbacks) {
99
86
  options = extendDeep(defaultWhisperLanguageDetectionOptions, options);
100
87
  if (sourceRawAudio.sampleRate !== 16000) {
101
88
  throw new Error('Source audio must have a sample rate of 16000 Hz');
102
89
  }
103
- if (!isMultilingualModel(modelName)) {
90
+ if (!isMultilingualModel(modelId)) {
104
91
  throw new Error(`Language detection is only supported with multilingual models.`);
105
92
  }
106
93
  if (options.temperature < 0) {
107
94
  throw new Error(`Temperature cannot be negative`);
108
95
  }
109
- // Select encoder ONNX provider
110
- const encoderProviders = options.encoderProvider ? [options.encoderProvider] : getDefaultEncoderProvidersForModel(modelName);
111
- // Select decoder ONNX provider
112
- const decoderProviders = options.decoderProvider ? [options.decoderProvider] : [];
113
- const whisper = new Whisper(modelName, modelDir, encoderProviders, decoderProviders);
96
+ const whisper = new Whisper(modelId, modelPath, libPath);
114
97
  async function detectLanguageForPart(partAudio) {
115
- const audioFeatures = await whisper.encodeAudio(partAudio);
116
- const partResults = await whisper.detectLanguage(audioFeatures, options.temperature);
98
+ const partResults = await whisper.detectLanguage(partAudio, options, callbacks);
117
99
  return partResults;
118
100
  }
119
- const results = await detectSpeechLanguageByParts(sourceRawAudio, detectLanguageForPart);
101
+ const results = await detectSpeechLanguageByParts(sourceRawAudio, detectLanguageForPart, undefined, undefined, callbacks);
120
102
  results.sort((entry1, entry2) => entry2.probability - entry1.probability);
121
103
  return results;
122
104
  }
123
- export async function detectVoiceActivity(sourceRawAudio, modelName, modelDir, options) {
124
- options = extendDeep(defaultWhisperVADOptions, options);
125
- if (sourceRawAudio.sampleRate !== 16000) {
126
- throw new Error('Source audio must have a sample rate of 16000 Hz');
127
- }
128
- if (options.temperature < 0) {
129
- throw new Error(`Temperature cannot be negative`);
130
- }
131
- const audioSamples = sourceRawAudio.audioChannels[0];
132
- const partDuration = 5;
133
- const maxSamplesCountForPart = sourceRawAudio.sampleRate * partDuration;
134
- // Select encoder ONNX provider
135
- const encoderProviders = options.encoderProvider ? [options.encoderProvider] : getDefaultEncoderProvidersForModel(modelName);
136
- // Select decoder ONNX provider
137
- const decoderProviders = options.decoderProvider ? [options.decoderProvider] : [];
138
- const whisper = new Whisper(modelName, modelDir, encoderProviders, decoderProviders);
139
- const partProbabilities = [];
140
- for (let sampleOffset = 0; sampleOffset < audioSamples.length; sampleOffset += maxSamplesCountForPart) {
141
- const partSamples = sliceRawAudio(sourceRawAudio, sampleOffset, sampleOffset + maxSamplesCountForPart);
142
- const samplesCountForPart = partSamples.audioChannels[0].length;
143
- const startTime = sampleOffset / sourceRawAudio.sampleRate;
144
- const endTime = (sampleOffset + samplesCountForPart) / sourceRawAudio.sampleRate;
145
- const encodedPartSamples = await whisper.encodeAudio(partSamples);
146
- const probabilityForPart = await whisper.detectVoiceActivity(encodedPartSamples, options.temperature);
147
- partProbabilities.push({
148
- type: 'segment',
149
- text: '',
150
- startTime,
151
- endTime,
152
- confidence: probabilityForPart,
153
- });
154
- }
155
- return { partProbabilities };
156
- }
157
105
  export class Whisper {
158
- modelName;
159
- modelDir;
160
- encoderExecutionProviders;
161
- decoderExecutionProviders;
106
+ modelId;
107
+ modelPath;
108
+ libPath;
162
109
  isMultiligualModel;
163
- audioEncoder;
164
- textDecoder;
165
110
  tiktoken;
166
- tokenConfig;
111
+ context;
112
+ specialTokens;
167
113
  randomGen;
168
- constructor(modelName, modelDir, encoderExecutionProviders, decoderExecutionProviders, prngSeed = 1234) {
169
- this.modelName = modelName;
170
- this.modelDir = modelDir;
171
- this.encoderExecutionProviders = encoderExecutionProviders;
172
- this.decoderExecutionProviders = decoderExecutionProviders;
173
- this.isMultiligualModel = isMultilingualModel(this.modelName);
174
- if (this.isMultiligualModel) {
175
- this.tokenConfig = {
176
- endOfTextToken: 50257,
177
- startOfTextToken: 50258,
178
- languageTokensStart: 50259,
179
- languageTokensEnd: 50358,
180
- translateTaskToken: 50358,
181
- transcribeTaskToken: 50359,
182
- startOfPromptToken: 50361,
183
- nonSpeechToken: 50362,
184
- noTimestampsToken: 50363,
185
- timestampTokensStart: 50364,
186
- timestampTokensEnd: 50364 + 1501,
187
- };
188
- }
189
- else {
190
- this.tokenConfig = {
191
- endOfTextToken: 50256,
192
- startOfTextToken: 50257,
193
- languageTokensStart: 50258,
194
- languageTokensEnd: 50358,
195
- translateTaskToken: 50358,
196
- transcribeTaskToken: 50359,
197
- startOfPromptToken: 50360,
198
- nonSpeechToken: 50361,
199
- noTimestampsToken: 50362,
200
- timestampTokensStart: 50363,
201
- timestampTokensEnd: 50363 + 1501,
202
- };
203
- }
114
+ constructor(modelId, modelPath, libPath, prngSeed = 1234) {
115
+ this.modelId = modelId;
116
+ this.modelPath = modelPath;
117
+ this.libPath = libPath;
118
+ this.isMultiligualModel = isMultilingualModel(this.modelId);
119
+ this.specialTokens = this.isMultiligualModel ? multilingualSpecialTokens : englishOnlySpecialTokens;
204
120
  this.randomGen = new XorShift32PRNG(murmurHash3_int32Input(prngSeed));
205
121
  }
206
- async recognize(rawAudio, task, language, options, logitFilter, onPart) {
207
- await this.initializeIfNeeded();
208
- const logger = new Logger();
122
+ async recognize(rawAudio, task, language, options, logitFilter, callbacks) {
123
+ await this.initializeIfNeeded(options, callbacks);
124
+ const logger = new Logger(callbacks.logLevel);
209
125
  options = extendDeep(defaultWhisperOptions, options);
210
- options.model = this.modelName;
126
+ options.model = this.modelId;
211
127
  if (!options.timestampAccuracy) {
212
128
  options.timestampAccuracy = this.defaultTimestampAccuracy;
213
129
  }
@@ -230,13 +146,15 @@ export class Whisper {
230
146
  };
231
147
  }
232
148
  for (let audioOffset = 0; audioOffset < audioSamples.length;) {
149
+ callbacks?.abortSignal?.throwIfAborted();
233
150
  const segmentStartTime = audioOffset / sampleRate;
234
151
  await logger.startAsync(`\nPrepare audio part at time position ${segmentStartTime.toFixed(2)}`, undefined, chalk.magentaBright);
235
- const audioPartSamples = audioSamples.slice(audioOffset, audioOffset + maxAudioSamplesPerPart);
152
+ const audioPartSamples = audioSamples.subarray(audioOffset, audioOffset + maxAudioSamplesPerPart);
236
153
  const audioPartRawAudio = { audioChannels: [audioPartSamples], sampleRate };
237
154
  const audioPartDuration = getRawAudioDuration(audioPartRawAudio);
238
155
  logger.end();
239
- const audioPartFeatures = await this.encodeAudio(audioPartRawAudio);
156
+ await this.encodeSamples(audioPartSamples, false, options, callbacks);
157
+ await logger.startAsync(`Prepare prompt`);
240
158
  const isFirstPart = audioOffset === 0;
241
159
  const isFinalPart = audioOffset + maxAudioSamplesPerPart >= audioSamples.length;
242
160
  let initialTokens = [];
@@ -245,15 +163,15 @@ export class Whisper {
245
163
  if (promptTokens.length > largestMaximumTokensPerPart) {
246
164
  promptTokens = promptTokens.slice(promptTokens.length - largestMaximumTokensPerPart);
247
165
  }
248
- initialTokens = [this.tokenConfig.startOfPromptToken, ...promptTokens];
166
+ initialTokens = [this.specialTokens.startOfPromptToken, ...promptTokens];
249
167
  }
250
168
  else if (options.autoPromptParts && previousPartTextTokens.length > 0) {
251
- initialTokens = [this.tokenConfig.startOfPromptToken, ...previousPartTextTokens];
169
+ initialTokens = [this.specialTokens.startOfPromptToken, ...previousPartTextTokens];
252
170
  }
253
171
  initialTokens = [...initialTokens, ...this.getTextStartTokens(language, task, !decodeTimestampTokens)];
254
172
  //logger.log(`Initial tokens count: ${initialTokens.length}`)
255
173
  logger.end();
256
- let { decodedTokens: partTokens, decodedTokensConfidence: partTokensConfidence, decodedTokensCrossAttentionQKs: partTokensCrossAttentionQKs, decodedTokensDecodingTime: partTokensDecodingTime, decodedTokensInferenceTime: partTokensInferenceTime, decodedTokensOverheadTime: partTokensOverheadTime, } = await this.decodeTokens(audioPartFeatures, initialTokens, audioPartDuration, isFirstPart, isFinalPart, options, wrappedLogitFilter);
174
+ let { decodedTokens: partTokens, decodedTokensConfidence: partTokensConfidence, decodedTokensCrossAttentionQKs: partTokensCrossAttentionQKs, decodedTokensDecodingTime: partTokensDecodingTime, decodedTokensInferenceTime: partTokensInferenceTime, decodedTokensOverheadTime: partTokensOverheadTime, } = await this.decodeTokens(initialTokens, audioPartDuration, isFirstPart, isFinalPart, options, wrappedLogitFilter, callbacks);
257
175
  const lastToken = partTokens[partTokens.length - 1];
258
176
  const lastTokenIsTimestamp = this.isTimestampToken(lastToken);
259
177
  let audioEndOffset;
@@ -267,31 +185,19 @@ export class Whisper {
267
185
  const segmentEndTime = audioEndOffset / sampleRate;
268
186
  const segmentFrameCount = this.secondsRangeToFrameCount(segmentStartTime, segmentEndTime);
269
187
  await logger.startAsync(`Extract timeline for part (timestamp accuracy: ${options.timestampAccuracy})`);
270
- if (partTokens.length !== partTokensCrossAttentionQKs.length) {
271
- throw new Error('Unexpected: partTokens.length !== partCrossAttentionQKs.length');
272
- }
273
188
  // Prepare tokens
274
189
  partTokens = partTokens.slice(initialTokens.length);
275
190
  partTokensConfidence = partTokensConfidence.slice(initialTokens.length);
276
191
  partTokensCrossAttentionQKs = partTokensCrossAttentionQKs.slice(initialTokens.length);
277
- // Find alignment path
278
- let alignmentHeads;
279
- if (options.timestampAccuracy === 'medium' || options.model === 'large-v3-turbo') {
280
- alignmentHeads = this.alignmentHeadIndexes;
281
- }
282
- else if (options.timestampAccuracy === 'high') {
283
- alignmentHeads = undefined;
284
- }
285
- else {
286
- throw new Error(`Unsupported timestamp accuracy '${options.timestampAccuracy}', can only be 'medium' or 'high'.`);
287
- }
288
- const alignmentPath = await this.findAlignmentPathFromQKs(partTokensCrossAttentionQKs, partTokens, 0, segmentFrameCount, alignmentHeads);
192
+ // Find alignment path using the cross attention query-key tensors
193
+ const alignmentHeadsIndexesToUse = undefined;
194
+ const alignmentPath = await this.findAlignmentPathFromCrossAttentionQKs(partTokensCrossAttentionQKs, partTokens, 0, segmentFrameCount, alignmentHeadsIndexesToUse);
289
195
  // Generate timeline from alignment path
290
196
  const partTimeline = await this.getTokenTimelineFromAlignmentPath(alignmentPath, partTokens, segmentStartTime, segmentEndTime, partTokensConfidence);
291
- if (onPart) {
197
+ if (callbacks?.onPart) {
292
198
  const partWordTimeline = this.tokenTimelineToWordTimeline(partTimeline, language);
293
199
  const partTranscript = this.tokensToText(partTokens);
294
- onPart(partTranscript, partTimeline, partWordTimeline);
200
+ callbacks.onPart(partTranscript, partTimeline, partWordTimeline);
295
201
  }
296
202
  // Add tokens to output
297
203
  allDecodedTokens.push(...partTokens);
@@ -309,12 +215,12 @@ export class Whisper {
309
215
  }
310
216
  audioOffset = audioEndOffset;
311
217
  logger.end();
312
- if (logLevelGreaterOrEqualTo('trace')) {
313
- const promptDecodingTime = partTokensDecodingTime[0];
218
+ if (logger.logLevelGreaterOrEqualTo('trace')) {
219
+ const promptProcessingTime = partTokensDecodingTime[0];
314
220
  const medianTokenDecodingTime = medianOfVector(partTokensDecodingTime.slice(1));
315
221
  const medianTokenInferenceTime = medianOfVector(partTokensInferenceTime.slice(1));
316
222
  const medianOverheadTime = medianOfVector(partTokensOverheadTime.slice(1));
317
- logger.log(`${chalk.blueBright('Context')}: ${initialTokens.length + partTokens.length} tokens (${initialTokens.length} prompt, ${partTokens.length} decoded)\n${chalk.blueBright('Prompt decode time')}: ${promptDecodingTime.toFixed(1)}ms\n${chalk.blueBright('Median token decode time')}: ${medianTokenDecodingTime.toFixed(1)}ms (${medianTokenInferenceTime.toFixed(1)}ms inference, ${medianOverheadTime.toFixed(2)}ms overhead)`, 'trace');
223
+ logger.log(`${chalk.blueBright('Context')}: ${initialTokens.length + partTokens.length} tokens (${initialTokens.length} prompt, ${partTokens.length} decoded)\n${chalk.blueBright('Prompt processing time')}: ${promptProcessingTime.toFixed(1)}ms\n${chalk.blueBright('Median token decode time')}: ${medianTokenDecodingTime.toFixed(1)}ms (${medianTokenInferenceTime.toFixed(1)}ms inference, ${medianOverheadTime.toFixed(2)}ms overhead)`, 'trace');
318
224
  }
319
225
  }
320
226
  // Convert token timeline to word timeline
@@ -324,8 +230,10 @@ export class Whisper {
324
230
  logger.end();
325
231
  return { transcript, timeline, allDecodedTokens };
326
232
  }
327
- async align(rawAudio, transcript, sourceLanguage, task, whisperAlignmentOptions) {
328
- await this.initializeTokenizerIfNeeded();
233
+ async align(rawAudio, transcript, sourceLanguage, task, whisperAlignmentOptions, callbacks) {
234
+ await this.initializeTokenizerIfNeeded(callbacks);
235
+ const logger = new Logger(callbacks.logLevel);
236
+ logger.start(`Tokenize transcript`);
329
237
  whisperAlignmentOptions = extendDeep(defaultWhisperAlignmentOptions, whisperAlignmentOptions);
330
238
  if (!whisperAlignmentOptions.timestampAccuracy) {
331
239
  whisperAlignmentOptions.timestampAccuracy = this.defaultTimestampAccuracy;
@@ -344,7 +252,7 @@ export class Whisper {
344
252
  const simplifiedTranscriptTokens = this.textToTokens(simplifiedTranscript);
345
253
  // Initialize custom logit filter that allows only the transcript tokens to be decoded
346
254
  // in order.
347
- const endOfTextToken = this.tokenConfig.endOfTextToken;
255
+ const endOfTextToken = this.specialTokens.endOfTextToken;
348
256
  const logitFilter = (logits, decodedTokens, isFirstPart, isFinalPart) => {
349
257
  const decodedTextTokens = decodedTokens.filter(token => this.isTextToken(token));
350
258
  const nextTokenToDecode = simplifiedTranscriptTokens[decodedTextTokens.length] ?? endOfTextToken;
@@ -364,7 +272,10 @@ export class Whisper {
364
272
  };
365
273
  // Set options for alignment
366
274
  const options = {
367
- model: this.modelName,
275
+ model: this.modelId,
276
+ enableGPU: whisperAlignmentOptions.enableGPU,
277
+ threadCount: whisperAlignmentOptions.threadCount,
278
+ gpuDeviceIndex: whisperAlignmentOptions.gpuDeviceIndex,
368
279
  temperature: 0.0,
369
280
  prompt: undefined,
370
281
  topCandidateCount: 1,
@@ -377,12 +288,11 @@ export class Whisper {
377
288
  endTokenThreshold: whisperAlignmentOptions.endTokenThreshold,
378
289
  includeEndTokenInCandidates: false,
379
290
  timestampAccuracy: whisperAlignmentOptions.timestampAccuracy,
380
- encoderProvider: whisperAlignmentOptions.encoderProvider,
381
- decoderProvider: whisperAlignmentOptions.decoderProvider,
382
291
  seed: undefined,
383
292
  };
293
+ logger.end();
384
294
  // Recognize
385
- const { timeline, allDecodedTokens } = await this.recognize(rawAudio, task, sourceLanguage, options, logitFilter);
295
+ const { timeline, allDecodedTokens } = await this.recognize(rawAudio, task, sourceLanguage, options, logitFilter, callbacks);
386
296
  {
387
297
  // If not all tokens were decoded, add the remaining ones to the timeline
388
298
  const lastKnownWordStartTime = timeline.length > 0 ? timeline[timeline.length - 1].startTime : 0;
@@ -418,33 +328,28 @@ export class Whisper {
418
328
  }
419
329
  return timeline;
420
330
  }
421
- async detectLanguage(audioFeatures, temperature) {
331
+ async detectLanguage(audioSamples, options, callbacks) {
422
332
  if (!this.isMultiligualModel) {
423
333
  throw new Error('Language detection is only supported with multilingual models');
424
334
  }
425
- await this.initializeDecoderSessionIfNeeded();
335
+ if (audioSamples.sampleRate !== 16000) {
336
+ throw new Error('Sample rate must be 16000 Hz');
337
+ }
338
+ if (audioSamples.audioChannels.length !== 1) {
339
+ throw new Error('Audio must be mono');
340
+ }
341
+ await this.initializeContextIfNeeded(options, { logLevel: callbacks.logLevel });
426
342
  // Prepare and run decoder
427
- const logger = new Logger();
343
+ const logger = new Logger(callbacks.logLevel);
428
344
  await logger.startAsync('Detect language with Whisper model');
429
- const sotToken = this.tokenConfig.startOfTextToken;
430
- const initialTokens = [sotToken];
431
- const offset = 0;
432
- const Onnx = await import('onnxruntime-node');
433
- const initialKvDimensions = this.getKvDimensions(1, initialTokens.length);
434
- const kvCacheTensor = new Onnx.Tensor('float32', new Float32Array(initialKvDimensions[0] * initialKvDimensions[1] * initialKvDimensions[2] * initialKvDimensions[3]), initialKvDimensions);
435
- const tokensTensor = new Onnx.Tensor('int64', new BigInt64Array(initialTokens.map(token => BigInt(token))), [1, initialTokens.length]);
436
- const offsetTensor = new Onnx.Tensor('int64', new BigInt64Array([BigInt(offset)]), []);
437
- const decoderInputs = {
438
- tokens: tokensTensor,
439
- audio_features: audioFeatures,
440
- kv_cache: kvCacheTensor,
441
- offset: offsetTensor
442
- };
443
- const decoderOutputs = await this.textDecoder.run(decoderInputs);
444
- const logitsBuffer = decoderOutputs['logits'].data;
445
- const tokenConfig = this.tokenConfig;
446
- const languageTokensLogits = Array.from(logitsBuffer.slice(tokenConfig.languageTokensStart, tokenConfig.languageTokensEnd));
447
- const languageTokensProbabilities = softmax(languageTokensLogits, temperature);
345
+ logger.log(``);
346
+ await this.encodeSamples(audioSamples.audioChannels[0], undefined, options, callbacks);
347
+ const specialTokens = this.specialTokens;
348
+ const initialTokens = [specialTokens.startOfTextToken];
349
+ await this.context.decodeTokens(initialTokens, 0, options.threadCount);
350
+ const logits = this.context.getLogits();
351
+ const languageTokensLogits = logits.subarray(specialTokens.languageTokensStart, specialTokens.languageTokensEnd);
352
+ const languageTokensProbabilities = softmax(languageTokensLogits, options.temperature);
448
353
  const results = [];
449
354
  for (const language in languageIdLookup) {
450
355
  const langId = languageIdLookup[language];
@@ -458,58 +363,69 @@ export class Whisper {
458
363
  logger.end();
459
364
  return results;
460
365
  }
461
- async detectVoiceActivity(audioFeatures, temperature) {
462
- await this.initializeDecoderSessionIfNeeded();
463
- // Prepare and run decoder
464
- const logger = new Logger();
465
- await logger.startAsync('Detect voice activity with Whisper model');
466
- const sotToken = this.tokenConfig.startOfTextToken;
467
- const initialTokens = [sotToken];
468
- const offset = 0;
469
- const Onnx = await import('onnxruntime-node');
470
- const initialKvDimensions = this.getKvDimensions(1, initialTokens.length);
471
- const kvCacheTensor = new Onnx.Tensor('float32', new Float32Array(initialKvDimensions[0] * initialKvDimensions[1] * initialKvDimensions[2] * initialKvDimensions[3]), initialKvDimensions);
472
- const tokensTensor = new Onnx.Tensor('int64', new BigInt64Array(initialTokens.map(token => BigInt(token))), [1, initialTokens.length]);
473
- const offsetTensor = new Onnx.Tensor('int64', new BigInt64Array([BigInt(offset)]), []);
474
- const decoderInputs = {
475
- tokens: tokensTensor,
476
- audio_features: audioFeatures,
477
- kv_cache: kvCacheTensor,
478
- offset: offsetTensor
479
- };
480
- const decoderOutputs = await this.textDecoder.run(decoderInputs);
481
- const logitsBuffer = decoderOutputs['logits'].data;
482
- const tokenConfig = this.tokenConfig;
483
- const logits = Array.from(logitsBuffer);
484
- const probabilities = softmax(logits, temperature);
485
- const noSpeechProbability = probabilities[tokenConfig.nonSpeechToken];
486
- return 1.0 - noSpeechProbability;
366
+ async encodeSamples(samples, useCustomMelConverter = false, options, callbacks) {
367
+ const logger = new Logger(callbacks.logLevel);
368
+ if (useCustomMelConverter) {
369
+ await logger.startAsync('Extract Mel spectrogram from audio part');
370
+ // Compute Mel spectrogram
371
+ const sampleRate = 16000;
372
+ const rawAudio = { audioChannels: [samples], sampleRate: 16000 };
373
+ const fftOrder = 400;
374
+ const fftWindowSize = 400;
375
+ const fftHopLength = 160;
376
+ const melBandCount = this.melBandCount;
377
+ const melFilterbank = this.melFilterbank;
378
+ const maxAudioSamples = sampleRate * 30;
379
+ const maxFrameCount = 3000;
380
+ const { melSpectrogram } = await computeMelSpectrogramUsingFilterbank(rawAudio, fftOrder, fftWindowSize, fftHopLength, melFilterbank, undefined, callbacks);
381
+ const frameCount = Math.min(melSpectrogram.length, maxFrameCount);
382
+ // Flatten, transpose, apply logarithm, and normalize Mel spectrogram
383
+ await logger.startAsync('Process Mel spectrogram');
384
+ const flattenedLogMelSpectrogram = new Float32Array(frameCount * melBandCount);
385
+ let maxLogMel = -Infinity;
386
+ for (let i = 0; i < melBandCount; i++) {
387
+ for (let j = 0; j < frameCount; j++) {
388
+ const mel = melSpectrogram[j][i];
389
+ const logMel = Math.log10(Math.max(mel, 1e-10));
390
+ if (logMel > maxLogMel) {
391
+ maxLogMel = logMel;
392
+ }
393
+ flattenedLogMelSpectrogram[(i * frameCount) + j] = logMel;
394
+ }
395
+ }
396
+ for (let i = 0; i < flattenedLogMelSpectrogram.length; i++) {
397
+ const logMel = flattenedLogMelSpectrogram[i];
398
+ const normalizedLogMel = (Math.max(logMel, maxLogMel - 8) + 4) / 4;
399
+ flattenedLogMelSpectrogram[i] = normalizedLogMel;
400
+ }
401
+ await logger.startAsync('Encode Mel spectrogram');
402
+ await this.context.encodeLogMelSpectrogram(flattenedLogMelSpectrogram, melBandCount);
403
+ }
404
+ else {
405
+ await logger.startAsync('Encode samples');
406
+ await this.context.encodeSamples(samples, options.threadCount);
407
+ }
408
+ logger.end();
487
409
  }
488
410
  // Decode tokens using the decoder model
489
- async decodeTokens(audioFeatures, initialTokens, audioDuration, isFirstPart, isFinalPart, options, logitFilter) {
490
- // Initialize
491
- await this.initializeTokenizerIfNeeded();
492
- await this.initializeDecoderSessionIfNeeded();
493
- const logger = new Logger();
411
+ async decodeTokens(initialTokens, audioDuration, isFirstPart, isFinalPart, options, logitFilter, callbacks) {
412
+ const logger = new Logger(callbacks.logLevel);
494
413
  await logger.startAsync('Decode text tokens with Whisper decoder model');
495
414
  options = extendDeep(defaultWhisperOptions, options);
496
- const Onnx = await import('onnxruntime-node');
497
415
  // Get token information
498
- const endOfTextToken = this.tokenConfig.endOfTextToken;
499
- const timestampTokensStart = this.tokenConfig.timestampTokensStart;
416
+ const endOfTextToken = this.specialTokens.endOfTextToken;
417
+ const timestampTokensStart = this.specialTokens.timestampTokensStart;
500
418
  const suppressedTextTokens = this.getSuppressedTextTokens();
501
419
  const suppressedMetadataTokens = this.getSuppressedMetadataTokens();
502
420
  const allowedPunctuationMarks = this.getAllowedPunctuationMarks();
503
421
  const spaceToken = this.textToTokens(' ')[0];
504
422
  // Initialize variables for decoding loop
505
423
  let decodedTokens = initialTokens.slice();
506
- const initialKvDimensions = this.getKvDimensions(1, decodedTokens.length);
507
- let kvCacheTensor = new Onnx.Tensor('float32', new Float32Array(initialKvDimensions[0] * initialKvDimensions[1] * initialKvDimensions[2] * initialKvDimensions[3]), initialKvDimensions);
508
424
  let decodedTokensTimestampLogits = [];
509
425
  let decodedTokensConfidence = [];
510
426
  let decodedTokensCrossAttentionQKs = [];
511
427
  for (let i = 0; i < decodedTokens.length; i++) {
512
- decodedTokensTimestampLogits.push(new Array(1501)); // Should the length be 1500 instead?
428
+ decodedTokensTimestampLogits.push(new Float32Array(1501)); // Should the length be 1500 instead?
513
429
  decodedTokensConfidence.push(1.0);
514
430
  decodedTokensCrossAttentionQKs.push(undefined);
515
431
  }
@@ -517,58 +433,40 @@ export class Whisper {
517
433
  let timestampTokenSeenCount = 0;
518
434
  let bufferedTokensToPrint = [];
519
435
  // Define method to add a token to output
520
- function addToken(tokenToAdd, timestampLogits, confidence, crossAttentionQKs) {
436
+ const addToken = (tokenToAdd, timestampLogits, confidence, crossAttentionQKs) => {
521
437
  decodedTokens.push(tokenToAdd);
522
438
  decodedTokensTimestampLogits.push(timestampLogits);
523
439
  decodedTokensConfidence.push(confidence);
524
440
  decodedTokensCrossAttentionQKs.push(crossAttentionQKs);
525
- }
441
+ if (callbacks?.onToken) {
442
+ callbacks.onToken(tokenToAdd, this.tokenToBytes(tokenToAdd));
443
+ }
444
+ };
526
445
  const maxTokensPerPart = Math.min(options.maxTokensPerPart, largestMaximumTokensPerPart);
527
446
  let decodedTokensInferenceTime = [];
528
447
  let decodedTokensDecodingTime = [];
529
448
  const tokenDecodingTimeTimer = new Timer();
530
449
  // Start decoding loop
531
450
  for (let decodedTokenCount = 0; decodedTokenCount < maxTokensPerPart; decodedTokenCount++) {
451
+ callbacks?.abortSignal?.throwIfAborted();
532
452
  if (decodedTokenCount > 0) {
533
453
  decodedTokensDecodingTime.push(tokenDecodingTimeTimer.getElapsedTimeAndRestart());
534
454
  }
535
455
  const isInitialState = decodedTokens.length === initialTokens.length;
536
456
  const atLeastOneTextTokenDecoded = decodedTokens.slice(initialTokens.length).some(token => this.isTextToken(token));
537
- // If not in initial state, reshape KV Cache tensor to accomodate a new output token
538
- if (!isInitialState) {
539
- const dims = kvCacheTensor.dims;
540
- const currentKvCacheGroups = splitFloat32Array(kvCacheTensor.data, dims[2] * dims[3]);
541
- const reshapedKvCacheTensor = new Onnx.Tensor('float32', new Float32Array(dims[0] * dims[1] * (decodedTokens.length) * dims[3]), [dims[0], dims[1], decodedTokens.length, dims[3]]);
542
- const reshapedKvCacheGroups = splitFloat32Array(reshapedKvCacheTensor.data, decodedTokens.length * dims[3]);
543
- for (let i = 0; i < dims[0]; i++) {
544
- reshapedKvCacheGroups[i].set(currentKvCacheGroups[i]);
545
- }
546
- kvCacheTensor = reshapedKvCacheTensor;
547
- }
548
457
  // Prepare values for decoder
549
458
  const tokensToDecode = isInitialState ? decodedTokens : [decodedTokens[decodedTokens.length - 1]];
550
459
  const offset = isInitialState ? 0 : decodedTokens.length;
551
- const tokensTensor = new Onnx.Tensor('int64', new BigInt64Array(tokensToDecode.map(token => BigInt(token))), [1, tokensToDecode.length]);
552
- const offsetTensor = new Onnx.Tensor('int64', new BigInt64Array([BigInt(offset)]), []);
553
- const decoderInputs = {
554
- tokens: tokensTensor,
555
- audio_features: audioFeatures,
556
- kv_cache: kvCacheTensor,
557
- offset: offsetTensor
558
- };
559
- //// Infer with ONNX decoder model
560
- const tokenInferenceTimeTimer = new Timer();
561
- const decoderOutputs = await this.textDecoder.run(decoderInputs);
562
- decodedTokensInferenceTime.push(tokenInferenceTimeTimer.elapsedTime);
563
- // Extract decoder model results
564
- const logitsBuffer = decoderOutputs['logits'].data;
565
- kvCacheTensor = decoderOutputs['output_kv_cache'];
566
- const crossAttentionQKsForTokenOnnx = decoderOutputs['cross_attention_qks'];
567
- const crossAttentionQKsForToken = makeOnnxLikeFloat32Tensor(crossAttentionQKsForTokenOnnx);
568
- crossAttentionQKsForTokenOnnx.dispose();
460
+ //// Infer
461
+ const tokenInferenceTimer = new Timer();
462
+ await this.context.decodeTokens(tokensToDecode, offset, options.threadCount);
463
+ decodedTokensInferenceTime.push(tokenInferenceTimer.elapsedTime);
464
+ // Get cross-attention QKs
465
+ //const getCrossAttentionQKsTimer = new Timer()
466
+ const tokenCrossAttentionQKs = await this.context.getCrossAttentionQKs();
467
+ //getCrossAttentionQKsTimer.logAndRestart('getCrossAttentionQKs')
569
468
  // Get logits
570
- const resultLogitsFloatArrays = splitFloat32Array(logitsBuffer, logitsBuffer.length / decoderOutputs['logits'].dims[1]);
571
- const allTokenLogits = Array.from(resultLogitsFloatArrays[resultLogitsFloatArrays.length - 1]);
469
+ const allTokenLogits = this.context.getLogits();
572
470
  // Suppress metadata tokens in the suppression set
573
471
  for (const suppressedTokenIndex of suppressedMetadataTokens) {
574
472
  allTokenLogits[suppressedTokenIndex] = -Infinity;
@@ -577,7 +475,7 @@ export class Whisper {
577
475
  // If in initial state, suppress end-of-text token
578
476
  allTokenLogits[endOfTextToken] = -Infinity;
579
477
  }
580
- const timestampTokenLogits = allTokenLogits.slice(timestampTokensStart);
478
+ const timestampTokenLogits = allTokenLogits.subarray(timestampTokensStart);
581
479
  const decodeTimestampTokenIfNeeded = () => {
582
480
  // Try to decode a timestamp token, if needed
583
481
  // If timestamp tokens is disabled in options, don't decode a timestamp
@@ -587,7 +485,7 @@ export class Whisper {
587
485
  // If this is the first token in the part, unconditionally decode a timestamp token
588
486
  // for time 0.0
589
487
  if (isInitialState) {
590
- addToken(timestampTokensStart, timestampTokenLogits, 1.0, crossAttentionQKsForToken);
488
+ addToken(timestampTokensStart, timestampTokenLogits, 1.0, tokenCrossAttentionQKs);
591
489
  return true;
592
490
  }
593
491
  const previousTokenWasTimestamp = this.isTimestampToken(decodedTokens[decodedTokens.length - 1]);
@@ -600,20 +498,20 @@ export class Whisper {
600
498
  }
601
499
  // Derive token probabilities
602
500
  const allTokenProbabilities = softmax(allTokenLogits, 1.0);
603
- const allTokenLogProbabilities = logOfVector(allTokenProbabilities);
604
- const nonTimestampTokenLogProbs = allTokenLogProbabilities.slice(0, timestampTokensStart);
605
- // Find highest non-timestamp token
606
- const indexOfMaxNonTimestampLogProb = indexOfMax(nonTimestampTokenLogProbs);
607
- const valueOfMaxNonTimestampLogProb = nonTimestampTokenLogProbs[indexOfMaxNonTimestampLogProb];
608
- // Find highest timestamp token
609
- const timestampTokenLogProbs = allTokenLogProbabilities.slice(timestampTokensStart);
610
- const indexOfMaxTimestampLogProb = indexOfMax(timestampTokenLogProbs);
611
- // Compute the log of the sum of exponentials of the log probabilities
612
- // of the timestamp tokens
613
- const logSumExpOfTimestampTokenLogProbs = logSumExp(timestampTokenLogProbs);
501
+ const nonTimestampTokenProbs = allTokenProbabilities.subarray(0, timestampTokensStart);
502
+ // Find highest probability non-timestamp token
503
+ const indexOfMaxNonTimestampProb = indexOfMax(nonTimestampTokenProbs);
504
+ const valueOfMaxNonTimestampProb = nonTimestampTokenProbs[indexOfMaxNonTimestampProb];
505
+ const valueOfMaxNonTimestampLogProb = Math.log(valueOfMaxNonTimestampProb);
506
+ // Find highest probability timestamp token
507
+ const timestampTokenProbs = allTokenProbabilities.subarray(timestampTokensStart);
508
+ const indexOfMaxTimestampProb = indexOfMax(timestampTokenProbs);
509
+ // Compute the log of the sum of probabilities of the timestamp tokens
510
+ const sumOfTimestampTokenProbs = sumVector(timestampTokenProbs);
511
+ const logSumOfTimestampTokenProbs = Math.log(sumOfTimestampTokenProbs);
614
512
  // If the sum isn't greater than the log probability of the highest non-timestamp token,
615
513
  // don't decode a timestamp
616
- if (logSumExpOfTimestampTokenLogProbs <= valueOfMaxNonTimestampLogProb) {
514
+ if (logSumOfTimestampTokenProbs <= valueOfMaxNonTimestampLogProb) {
617
515
  return false;
618
516
  }
619
517
  // Decode a timestamp token
@@ -623,14 +521,14 @@ export class Whisper {
623
521
  const previousToken = decodedTokens[decodedTokens.length - 1];
624
522
  const previousTokenTimestampLogits = decodedTokensTimestampLogits[decodedTokensTimestampLogits.length - 1];
625
523
  const previousTokenConfidence = decodedTokensConfidence[decodedTokensConfidence.length - 1];
626
- addToken(previousToken, previousTokenTimestampLogits, previousTokenConfidence, crossAttentionQKsForToken);
524
+ addToken(previousToken, previousTokenTimestampLogits, previousTokenConfidence, tokenCrossAttentionQKs);
627
525
  lastTimestampTokenIndex = decodedTokens.length;
628
526
  }
629
527
  else {
630
528
  // Otherwise decode the highest probability timestamp
631
- const timestampToken = timestampTokensStart + indexOfMaxTimestampLogProb;
529
+ const timestampToken = timestampTokensStart + indexOfMaxTimestampProb;
632
530
  const confidence = allTokenProbabilities[timestampToken];
633
- addToken(timestampToken, timestampTokenLogits, confidence, crossAttentionQKsForToken);
531
+ addToken(timestampToken, timestampTokenLogits, confidence, tokenCrossAttentionQKs);
634
532
  }
635
533
  return true;
636
534
  };
@@ -669,7 +567,7 @@ export class Whisper {
669
567
  }
670
568
  // If filter caused all word token logits to be -Infinity, then there is no
671
569
  // other token to decode. Fall back to accept end-of-text
672
- if (nonTimestampTokenLogits.slice(0, endOfTextToken).every(logit => logit === -Infinity)) {
570
+ if (nonTimestampTokenLogits.subarray(0, endOfTextToken).every(logit => logit === -Infinity)) {
673
571
  shouldDecodeEndfOfTextToken = true;
674
572
  }
675
573
  }
@@ -686,7 +584,7 @@ export class Whisper {
686
584
  // If end-of-text token should be decoded, then add it and break
687
585
  // out of the loop
688
586
  if (shouldDecodeEndfOfTextToken) {
689
- addToken(endOfTextToken, timestampTokenLogits, 1.0, crossAttentionQKsForToken);
587
+ addToken(endOfTextToken, timestampTokenLogits, 1.0, tokenCrossAttentionQKs);
690
588
  break;
691
589
  }
692
590
  // Suppress end-of-text token if it shouldn't be included in candidates
@@ -763,7 +661,7 @@ export class Whisper {
763
661
  // Add chosen token
764
662
  const chosenToken = topCandidates[chosenCandidateRank].token;
765
663
  const chosenTokenConfidence = topCandidateProbabilities[chosenCandidateRank];
766
- addToken(chosenToken, timestampTokenLogits, chosenTokenConfidence, crossAttentionQKsForToken);
664
+ addToken(chosenToken, timestampTokenLogits, chosenTokenConfidence, tokenCrossAttentionQKs);
767
665
  // If chosen token is the end-of-text token, break
768
666
  if (chosenToken === endOfTextToken) {
769
667
  break;
@@ -792,8 +690,8 @@ export class Whisper {
792
690
  const sliceEndTokenIndex = lastTimestampTokenIndex;
793
691
  decodedTokens = decodedTokens.slice(0, sliceEndTokenIndex);
794
692
  decodedTokensTimestampLogits = decodedTokensTimestampLogits.slice(0, sliceEndTokenIndex);
795
- decodedTokensCrossAttentionQKs = decodedTokensCrossAttentionQKs.slice(0, sliceEndTokenIndex);
796
693
  decodedTokensConfidence = decodedTokensConfidence.slice(0, sliceEndTokenIndex);
694
+ decodedTokensCrossAttentionQKs = decodedTokensCrossAttentionQKs.slice(0, sliceEndTokenIndex);
797
695
  decodedTokensDecodingTime = decodedTokensDecodingTime.slice(0, sliceEndTokenIndex);
798
696
  decodedTokensInferenceTime = decodedTokensInferenceTime.slice(0, sliceEndTokenIndex);
799
697
  }
@@ -811,68 +709,13 @@ export class Whisper {
811
709
  decodedTokensOverheadTime,
812
710
  };
813
711
  }
814
- // Encode audio using the encoder model
815
- async encodeAudio(rawAudio) {
816
- await this.initializeEncoderSessionIfNeeded();
817
- const Onnx = await import('onnxruntime-node');
818
- const logger = new Logger();
819
- const audioSamples = rawAudio.audioChannels[0];
820
- const sampleRate = rawAudio.sampleRate;
821
- const fftOrder = 400;
822
- const fftWindowSize = 400;
823
- const fftHopLength = 160;
824
- const filterbankCount = this.filterbankCount;
825
- const filterbanks = this.filterbanks;
826
- const maxAudioSamples = sampleRate * 30;
827
- const maxAudioFrames = 3000;
828
- if (sampleRate !== 16000) {
829
- throw new Error('Audio must have a sample rate of 16000 Hz');
830
- }
831
- if (audioSamples.length > maxAudioSamples) {
832
- throw new Error(`Audio part is longer than 30 seconds`);
833
- }
834
- await logger.startAsync('Extract Mel spectrogram from audio part');
835
- // Pad audio samples to ensure that have a duration of 30 seconds
836
- const paddedAudioSamples = new Float32Array(maxAudioSamples);
837
- paddedAudioSamples.set(audioSamples, 0);
838
- const rawAudioPart = { audioChannels: [paddedAudioSamples], sampleRate };
839
- // Compute Mel spectrogram
840
- const { melSpectrogram } = await computeMelSpectrogramUsingFilterbanks(rawAudioPart, fftOrder, fftWindowSize, fftHopLength, filterbanks);
841
- // Flatten, transpose, apply logarithm and normalize Mel spectrogram
842
- await logger.startAsync('Process Mel spectrogram');
843
- const flattenedLogMelSpectrogram = new Float32Array(maxAudioFrames * filterbankCount);
844
- let maxLogMel = -Infinity;
845
- for (let i = 0; i < filterbankCount; i++) {
846
- for (let j = 0; j < maxAudioFrames; j++) {
847
- const mel = melSpectrogram[j][i];
848
- const logMel = Math.log10(Math.max(mel, 1e-10));
849
- if (logMel > maxLogMel) {
850
- maxLogMel = logMel;
851
- }
852
- flattenedLogMelSpectrogram[(i * maxAudioFrames) + j] = logMel;
853
- }
854
- }
855
- for (let i = 0; i < flattenedLogMelSpectrogram.length; i++) {
856
- const logMel = flattenedLogMelSpectrogram[i];
857
- const normalizedLogMel = (Math.max(logMel, maxLogMel - 8) + 4) / 4;
858
- flattenedLogMelSpectrogram[i] = normalizedLogMel;
859
- }
860
- // Run the encoder model
861
- await logger.startAsync('Encode Mel spectrogram with Whisper encoder model');
862
- const inputTensor = new Onnx.Tensor('float32', flattenedLogMelSpectrogram, [1, filterbankCount, maxAudioFrames]);
863
- const encoderInputs = { mel: inputTensor };
864
- const encoderOutputs = await this.audioEncoder.run(encoderInputs);
865
- const encodedAudioFeatures = encoderOutputs['output'];
866
- logger.end();
867
- return encodedAudioFeatures;
868
- }
869
712
  tokenTimelineToWordTimeline(tokenTimeline, language) {
870
713
  function isSeparatorCharacter(char) {
871
714
  const nonSeparatingPunctuation = [`'`, `-`, `.`, `·`, `•`];
872
715
  if (nonSeparatingPunctuation.includes(char)) {
873
716
  return false;
874
717
  }
875
- return isWhitespace(char) || includesPunctuation(char);
718
+ return isAllWhitespace(char) || includesPunctuation(char);
876
719
  }
877
720
  function startsWithSeparatorCharacter(text) {
878
721
  return isSeparatorCharacter(text[0]);
@@ -973,31 +816,31 @@ export class Whisper {
973
816
  }
974
817
  return tokenTimeline;
975
818
  }
976
- async findAlignmentPathFromQKs(qksTensors, tokens, segmentStartFrame, segmentEndFrame, headIndexes) {
977
- const segmentFrameCount = segmentEndFrame - segmentStartFrame;
978
- if (segmentFrameCount === 0 || tokens.length === 0 || qksTensors.length === 0) {
819
+ async findAlignmentPathFromCrossAttentionQKs(crossAttentionQKs, tokens, partStartFrameIndex, partEndFrameIndex, alignmentHeadsIndexesToUse) {
820
+ const partFrameCount = partEndFrameIndex - partStartFrameIndex;
821
+ if (partFrameCount === 0 || tokens.length === 0 || crossAttentionQKs.length === 0 || crossAttentionQKs[0].data.length === 0) {
979
822
  return [];
980
823
  }
981
- const tokenCount = qksTensors.length;
982
- const layerCount = qksTensors[0].dims[0];
983
- const headCount = qksTensors[0].dims[2];
984
- const frameCount = qksTensors[0].dims[4];
985
- if (!headIndexes) {
986
- headIndexes = getIntegerRange(0, layerCount * headCount);
987
- }
988
- // Load attention head weights from tensors
989
- const attentionHeads = []; // structure: [heads, tokens, frames]
990
- for (const headIndex of headIndexes) {
991
- const attentionHead = []; // structure: [tokens, frames]
824
+ // crossAttentionQKs internal dimensions: [heads, tokens = 1, frames]
825
+ const tokenCount = crossAttentionQKs.length;
826
+ const headCount = Number(crossAttentionQKs[0].dimensions[0]);
827
+ const frameCount = Number(crossAttentionQKs[0].dimensions[2]);
828
+ if (!alignmentHeadsIndexesToUse) {
829
+ alignmentHeadsIndexesToUse = getIntegerRange(0, headCount);
830
+ }
831
+ // Initialize attention head arrays
832
+ const attentionHeads = []; // dimensions: [heads, tokens, frames]
833
+ for (const headIndex of alignmentHeadsIndexesToUse) {
834
+ const head = [];
835
+ const startIndexInBuffer = headIndex * frameCount;
836
+ const endIndexInBuffer = startIndexInBuffer + partFrameCount;
992
837
  for (let tokenIndex = 0; tokenIndex < tokenCount; tokenIndex++) {
993
- const bufferOffset = headIndex * frameCount;
994
- const startIndexInBuffer = bufferOffset + segmentStartFrame;
995
- const endIndexInBuffer = bufferOffset + segmentEndFrame;
996
- const framesForHead = qksTensors[tokenIndex].data.slice(startIndexInBuffer, endIndexInBuffer);
997
- attentionHead.push(framesForHead);
838
+ const data = crossAttentionQKs[tokenIndex].data.subarray(startIndexInBuffer, endIndexInBuffer);
839
+ head.push(data);
998
840
  }
999
- attentionHeads.push(attentionHead);
841
+ attentionHeads.push(head);
1000
842
  }
843
+ // Initialize settings
1001
844
  const applySoftmax = true;
1002
845
  const normalize = true;
1003
846
  const applyMedianFilter = true;
@@ -1042,11 +885,11 @@ export class Whisper {
1042
885
  }
1043
886
  }
1044
887
  }
1045
- // Compute the mean of the selected attention heads for all layers
888
+ // Compute the mean of the selected attention heads for each frame
1046
889
  const frameMeansForToken = [];
1047
890
  for (let tokenIndex = 0; tokenIndex < tokenCount; tokenIndex++) {
1048
- const meansForFrames = new Float32Array(segmentFrameCount);
1049
- for (let frameIndex = 0; frameIndex < segmentFrameCount; frameIndex++) {
891
+ const meansForFrames = new Float32Array(partFrameCount);
892
+ for (let frameIndex = 0; frameIndex < partFrameCount; frameIndex++) {
1050
893
  let sum = 0;
1051
894
  for (const head of attentionHeads) {
1052
895
  sum += head[tokenIndex][frameIndex];
@@ -1058,40 +901,90 @@ export class Whisper {
1058
901
  }
1059
902
  // Anchor timestamp tokens timestamps to their original values, if enabled
1060
903
  if (anchorTimestampTokens) {
1061
- const timestampTokensStart = this.tokenConfig.timestampTokensStart;
904
+ const timestampTokensStart = this.specialTokens.timestampTokensStart;
1062
905
  for (let tokenIndex = 0; tokenIndex < tokens.length; tokenIndex++) {
1063
906
  const token = tokens[tokenIndex];
1064
907
  if (this.isTimestampToken(token)) {
1065
908
  let timestampFrame = token - timestampTokensStart;
1066
- timestampFrame = clip(timestampFrame, segmentStartFrame, segmentEndFrame - 1);
909
+ timestampFrame = clip(timestampFrame, partStartFrameIndex, partEndFrameIndex - 1);
1067
910
  frameMeansForToken[tokenIndex][timestampFrame] = 100;
1068
911
  }
1069
912
  }
1070
913
  }
1071
914
  // Perform DTW to align tokens indexes to frame indexes
1072
915
  const tokenIndexes = getIntegerRange(0, tokenCount);
1073
- const frameIndexes = getIntegerRange(0, segmentFrameCount);
916
+ const frameIndexes = getIntegerRange(0, partFrameCount);
1074
917
  let { path } = alignDTWWindowed(tokenIndexes, frameIndexes, (tokenIndex, frameIndex) => {
1075
918
  return -frameMeansForToken[tokenIndex][frameIndex];
1076
- }, segmentFrameCount);
1077
- path = path.map(entry => ({ source: entry.source, dest: segmentStartFrame + entry.dest }));
919
+ }, partFrameCount);
920
+ path = path.map(entry => ({ source: entry.source, dest: partStartFrameIndex + entry.dest }));
1078
921
  return path;
1079
922
  }
1080
- async initializeIfNeeded() {
1081
- await this.initializeTokenizerIfNeeded();
1082
- await this.initializeEncoderSessionIfNeeded();
1083
- await this.initializeDecoderSessionIfNeeded();
923
+ async initializeIfNeeded(options, callbacks) {
924
+ await this.initializeTokenizerIfNeeded(callbacks);
925
+ await this.initializeContextIfNeeded(options, callbacks);
926
+ }
927
+ async initializeContextIfNeeded(options, callbacks) {
928
+ if (this.context) {
929
+ return;
930
+ }
931
+ const logger = new Logger(callbacks.logLevel);
932
+ const modelId = this.modelId;
933
+ const modelFilePath = this.modelPath;
934
+ const libPath = this.libPath;
935
+ let libFilePath;
936
+ if (process.platform === 'win32') {
937
+ libFilePath = resolvePath(libPath, 'whisper.dll');
938
+ }
939
+ else if (process.platform === 'darwin') {
940
+ libFilePath = resolvePath(libPath, 'libwhisper.0.dylib');
941
+ }
942
+ else if (process.platform === 'linux') {
943
+ libFilePath = resolvePath(libPath, 'libwhisper.so.0');
944
+ }
945
+ else {
946
+ throw new Error(`Unsupported platform`);
947
+ }
948
+ await logger.startAsync(`Load whisper.cpp model '${modelId}'`);
949
+ this.context = new WhisperCppContext();
950
+ let alignmentHeadsPreset;
951
+ let alignmentHeadsTopCount = 0;
952
+ if (options.timestampAccuracy == 'high') {
953
+ alignmentHeadsPreset = WhisperAlignmentHeadsPreset.WHISPER_AHEADS_N_TOP_MOST;
954
+ alignmentHeadsTopCount = whisperModelIdToTextLayerCount[modelId];
955
+ }
956
+ else {
957
+ alignmentHeadsPreset = whisperModelIdToAlignmentHeadsPreset[modelId];
958
+ }
959
+ const contextOptions = {
960
+ libFilePath,
961
+ modelFilePath,
962
+ // Force GPU option to be enabled for all GPU and CPU builds
963
+ // The `enableGPU` option in `WhisperOptions` doesn't impact this
964
+ enableGPU: true,
965
+ // Flash attention must be disabled for timestamp extraction to be possible
966
+ // in the way it's done here
967
+ enableFlashAttention: false,
968
+ // Device index is passed. Defaults to 0
969
+ gpuDeviceIndex: options.gpuDeviceIndex,
970
+ alignmentHeadsPreset,
971
+ alignmentHeadsTopCount,
972
+ //logLevel: logger.logLevelGreaterOrEqualTo('trace') ? GgmlLogLevel.GGML_LOG_LEVEL_INFO : GgmlLogLevel.GGML_LOG_LEVEL_WARN,
973
+ logLevel: GgmlLogLevel.GGML_LOG_LEVEL_WARN,
974
+ };
975
+ await this.context.initialize(contextOptions);
976
+ logger.end();
1084
977
  }
1085
- async initializeTokenizerIfNeeded() {
978
+ async initializeTokenizerIfNeeded(callbacks) {
1086
979
  if (this.tiktoken) {
1087
980
  return;
1088
981
  }
1089
- const logger = new Logger();
982
+ const logger = new Logger(callbacks.logLevel);
1090
983
  await logger.startAsync('Load tokenizer data');
1091
- const tiktokenModulePackagePath = await loadPackage('whisper-tiktoken-data');
984
+ const tiktokenModulePackagePath = await loadPackage('whisper-tiktoken-data', callbacks);
1092
985
  const tiktokenDataFilePath = joinPath(tiktokenModulePackagePath, this.isMultiligualModel ? 'multilingual.tiktoken' : 'gpt2.tiktoken');
1093
986
  let tiktokenData = await readFileAsUtf8(tiktokenDataFilePath);
1094
- const tokenConfig = this.tokenConfig;
987
+ const tokenConfig = this.specialTokens;
1095
988
  const metadataTokens = {
1096
989
  [tokenConfig.endOfTextToken]: '[EndOfText]',
1097
990
  [tokenConfig.startOfTextToken]: '[StartOfText]',
@@ -1107,12 +1000,12 @@ export class Whisper {
1107
1000
  }
1108
1001
  const languageTokenCount = tokenConfig.languageTokensEnd - tokenConfig.languageTokensStart;
1109
1002
  for (let i = 0; i < languageTokenCount; i++) {
1110
- const tokenIndex = this.tokenConfig.languageTokensStart + i;
1003
+ const tokenIndex = this.specialTokens.languageTokensStart + i;
1111
1004
  metadataTokens[tokenIndex] = `[Language_${i}]`;
1112
1005
  }
1113
1006
  const timestampTokensCount = 1501;
1114
1007
  for (let i = 0; i <= timestampTokensCount; i++) {
1115
- const tokenIndex = this.tokenConfig.timestampTokensStart + i;
1008
+ const tokenIndex = this.specialTokens.timestampTokensStart + i;
1116
1009
  const tokenTime = this.timestampTokenToSeconds(tokenIndex);
1117
1010
  metadataTokens[tokenIndex] = `[Timestamp_${tokenTime.toFixed(2)}]`;
1118
1011
  }
@@ -1125,72 +1018,33 @@ export class Whisper {
1125
1018
  this.tiktoken = new Tiktoken(tiktokenData, inverseMetadataTokensLookup, patternString);
1126
1019
  logger.end();
1127
1020
  }
1128
- async initializeEncoderSessionIfNeeded() {
1129
- if (this.audioEncoder) {
1130
- return;
1131
- }
1132
- const logger = new Logger();
1133
- const onnxSessionOptions = getOnnxSessionOptions({ executionProviders: this.encoderExecutionProviders });
1134
- const onnxProvidersString = onnxSessionOptions.executionProviders.length > 0 ? `${onnxSessionOptions.executionProviders.join(', ')}` : `default`;
1135
- await logger.startAsync(`Create encoder inference session for model '${this.modelName}' (ONNX provider: ${onnxProvidersString})`);
1136
- const encoderFilePath = joinPath(this.modelDir, 'encoder.onnx');
1137
- const Onnx = await import('onnxruntime-node');
1138
- this.audioEncoder = await Onnx.InferenceSession.create(encoderFilePath, onnxSessionOptions);
1139
- logger.end();
1140
- }
1141
- async initializeDecoderSessionIfNeeded() {
1142
- if (this.textDecoder) {
1143
- return;
1144
- }
1145
- const logger = new Logger();
1146
- const onnxSessionOptions = getOnnxSessionOptions({ executionProviders: this.decoderExecutionProviders });
1147
- const onnxProvidersString = onnxSessionOptions.executionProviders.length > 0 ? `${onnxSessionOptions.executionProviders.join(', ')}` : `default`;
1148
- await logger.startAsync(`Create decoder inference session for model '${this.modelName}' (ONNX provider: ${onnxProvidersString})`);
1149
- const decoderFilePath = joinPath(this.modelDir, 'decoder.onnx');
1150
- const Onnx = await import('onnxruntime-node');
1151
- this.textDecoder = await Onnx.InferenceSession.create(decoderFilePath, onnxSessionOptions);
1152
- logger.end();
1153
- }
1154
- getKvDimensions(groupCount, length) {
1155
- const modelName = this.modelName;
1156
- if (modelName === 'tiny' || modelName === 'tiny.en') {
1157
- return [8, groupCount, length, 384];
1158
- }
1159
- else if (modelName === 'base' || modelName === 'base.en') {
1160
- return [12, groupCount, length, 512];
1161
- }
1162
- else if (modelName === 'small' || modelName === 'small.en') {
1163
- return [24, groupCount, length, 768];
1164
- }
1165
- else if (modelName === 'medium' || modelName === 'medium.en') {
1166
- return [48, groupCount, length, 1024];
1167
- }
1168
- else if (modelName === 'large-v1' || modelName === 'large-v2' || modelName === 'large-v3' || modelName === 'large-v3-turbo') {
1169
- return [64, groupCount, length, 1280];
1170
- }
1171
- else {
1172
- throw new Error(`Unsupported model: ${modelName}`);
1173
- }
1174
- }
1175
1021
  getTextStartTokens(language, task, disableTimestamps = false) {
1176
- const startOfTextToken = this.tokenConfig.startOfTextToken;
1022
+ const startOfTextToken = this.specialTokens.startOfTextToken;
1177
1023
  let tokens;
1178
1024
  if (this.isMultiligualModel) {
1179
- const languageToken = this.tokenConfig.languageTokensStart + languageIdLookup[language];
1180
- const taskToken = task === 'translate' ? this.tokenConfig.translateTaskToken : this.tokenConfig.transcribeTaskToken;
1025
+ const languageToken = this.specialTokens.languageTokensStart + languageIdLookup[language];
1026
+ const taskToken = task === 'translate' ? this.specialTokens.translateTaskToken : this.specialTokens.transcribeTaskToken;
1181
1027
  tokens = [startOfTextToken, languageToken, taskToken];
1182
1028
  }
1183
1029
  else {
1184
1030
  tokens = [startOfTextToken];
1185
1031
  }
1186
1032
  if (disableTimestamps) {
1187
- tokens.push(this.tokenConfig.noTimestampsToken);
1033
+ tokens.push(this.specialTokens.noTimestampsToken);
1188
1034
  }
1189
1035
  return tokens;
1190
1036
  }
1191
1037
  tokenToText(token, includeMetadataTokens = false) {
1192
1038
  return this.tokensToText([token], includeMetadataTokens);
1193
1039
  }
1040
+ tokenToBytes(token) {
1041
+ return this.tiktoken.decode_single_token_bytes(token);
1042
+ }
1043
+ tokensToBytes(tokens) {
1044
+ const tokensBytes = tokens.map(token => this.tokenToBytes(token));
1045
+ const concatenatedTokensBytes = concatUint8Arrays(tokensBytes);
1046
+ return concatenatedTokensBytes;
1047
+ }
1194
1048
  tokensToText(tokens, includeMetadataTokens = false) {
1195
1049
  tokens.forEach(token => this.assertIsValidToken(token));
1196
1050
  if (includeMetadataTokens === false) {
@@ -1199,10 +1053,10 @@ export class Whisper {
1199
1053
  if (tokens.length === 0) {
1200
1054
  return '';
1201
1055
  }
1202
- const decodedBytes = this.tiktoken.decode(new Uint32Array(tokens));
1203
- const textDecoder = new TextDecoder();
1204
- const decodedString = textDecoder.decode(decodedBytes);
1205
1056
  try {
1057
+ const decodedBytes = this.tiktoken.decode(new Uint32Array(tokens));
1058
+ const textDecoder = new TextDecoder();
1059
+ const decodedString = textDecoder.decode(decodedBytes);
1206
1060
  return decodedString;
1207
1061
  }
1208
1062
  catch {
@@ -1213,32 +1067,32 @@ export class Whisper {
1213
1067
  return Array.from(this.tiktoken.encode(text));
1214
1068
  }
1215
1069
  isTextToken(token) {
1216
- return token < this.tokenConfig.endOfTextToken;
1070
+ return token < this.specialTokens.endOfTextToken;
1217
1071
  }
1218
1072
  isMetadataToken(token) {
1219
- return token >= this.tokenConfig.endOfTextToken;
1073
+ return token >= this.specialTokens.endOfTextToken;
1220
1074
  }
1221
1075
  isLanguageToken(token) {
1222
- return token >= this.tokenConfig.languageTokensStart && token < this.tokenConfig.languageTokensEnd;
1076
+ return token >= this.specialTokens.languageTokensStart && token < this.specialTokens.languageTokensEnd;
1223
1077
  }
1224
1078
  isTimestampToken(token) {
1225
- return token >= this.tokenConfig.timestampTokensStart;
1079
+ return token >= this.specialTokens.timestampTokensStart;
1226
1080
  }
1227
1081
  isNonTimestampToken(token) {
1228
- return token < this.tokenConfig.timestampTokensStart;
1082
+ return token < this.specialTokens.timestampTokensStart;
1229
1083
  }
1230
1084
  timestampTokenToSeconds(timestampToken) {
1231
1085
  this.assertIsValidToken(timestampToken);
1232
1086
  if (this.isNonTimestampToken(timestampToken)) {
1233
1087
  throw new Error(`Invalid timestamp token: ${timestampToken}`);
1234
1088
  }
1235
- let seconds = (timestampToken - this.tokenConfig.timestampTokensStart) * 0.02;
1089
+ let seconds = (timestampToken - this.specialTokens.timestampTokensStart) * 0.02;
1236
1090
  seconds = clip(seconds, 0.0, 30.0);
1237
1091
  return seconds;
1238
1092
  }
1239
1093
  isValidToken(token) {
1240
1094
  //return token < this.tokenConfig.timestampTokensEnd
1241
- return token <= this.tokenConfig.timestampTokensEnd;
1095
+ return token <= this.specialTokens.timestampTokensEnd;
1242
1096
  }
1243
1097
  assertIsValidToken(token) {
1244
1098
  if (!this.isValidToken(token)) {
@@ -1258,7 +1112,7 @@ export class Whisper {
1258
1112
  if (!this.isLanguageToken(languageToken)) {
1259
1113
  throw new Error(`Invalid language token: ${languageToken}`);
1260
1114
  }
1261
- let languageIndex = languageToken - this.tokenConfig.languageTokensStart;
1115
+ let languageIndex = languageToken - this.specialTokens.languageTokensStart;
1262
1116
  if (this.isEnglishOnlyModel) {
1263
1117
  languageIndex += 1;
1264
1118
  }
@@ -1266,20 +1120,17 @@ export class Whisper {
1266
1120
  get isEnglishOnlyModel() {
1267
1121
  return this.isMultiligualModel === false;
1268
1122
  }
1269
- get isLargeModel() {
1270
- return this.modelName.startsWith('large');
1123
+ get isLargeV3Model() {
1124
+ return this.modelId.startsWith('large-v3');
1271
1125
  }
1272
- get filterbankCount() {
1273
- return this.isLargeModel ? 128 : 80;
1126
+ get melBandCount() {
1127
+ return this.isLargeV3Model ? 128 : 80;
1274
1128
  }
1275
- get filterbanks() {
1276
- return this.isLargeModel ? filterbanks_128 : filterbanks_80;
1277
- }
1278
- get alignmentHeadIndexes() {
1279
- return alignmentHeadsIndexes[this.modelName];
1129
+ get melFilterbank() {
1130
+ return this.isLargeV3Model ? melFilterbank128 : melFilterbanks80;
1280
1131
  }
1281
1132
  get defaultTimestampAccuracy() {
1282
- if (this.modelName.startsWith('tiny') || this.modelName.startsWith('base')) {
1133
+ if (this.modelId.startsWith('tiny') || this.modelId.startsWith('base')) {
1283
1134
  return 'high';
1284
1135
  }
1285
1136
  else {
@@ -1326,7 +1177,7 @@ export class Whisper {
1326
1177
  getWordTokenData() {
1327
1178
  const wordTokenData = [];
1328
1179
  const nonWordTokenData = [];
1329
- for (let i = 0; i < this.tokenConfig.endOfTextToken; i++) {
1180
+ for (let i = 0; i < this.specialTokens.endOfTextToken; i++) {
1330
1181
  const tokenText = this.tokenToText(i, false);
1331
1182
  const isNonWordToken = /^[\s\p{Punctuation}\p{Symbol}]+$/u.test(tokenText);
1332
1183
  const containsInvalidUTF8 = containsInvalidCodepoint(tokenText);
@@ -1356,77 +1207,68 @@ export class Whisper {
1356
1207
  return tokensData;
1357
1208
  }
1358
1209
  }
1359
- export async function loadPackagesAndGetPaths(modelName, languageCode) {
1360
- if (modelName) {
1361
- modelName = normalizeWhisperModelName(modelName, languageCode);
1362
- }
1363
- else {
1364
- if (languageCode) {
1365
- const shortLanguageCode = getShortLanguageCode(languageCode);
1366
- modelName = shortLanguageCode === 'en' ? 'tiny.en' : 'tiny';
1210
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////
1211
+ // Utility methods
1212
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////
1213
+ export function isMultilingualModel(modelId) {
1214
+ return !isEnglishOnlyModel(modelId);
1215
+ }
1216
+ export function isEnglishOnlyModel(modelId) {
1217
+ return modelId.endsWith('.en');
1218
+ }
1219
+ export async function loadLibraryPackages(enableGPU, callbacks) {
1220
+ const arch = process.arch;
1221
+ const platform = process.platform;
1222
+ let packageName;
1223
+ const useMacOsGpuBuildByDefault = true;
1224
+ if (platform === 'win32' && arch === 'x64') {
1225
+ if (enableGPU) {
1226
+ packageName = 'whisper.cpp-lib-windows-x64-cublas-12.4.0';
1367
1227
  }
1368
1228
  else {
1369
- modelName = 'tiny';
1229
+ packageName = 'whisper.cpp-lib-windows-x64-cpu';
1370
1230
  }
1371
1231
  }
1372
- if (modelName.startsWith('large') && modelName !== 'large-v3-turbo') {
1373
- throw new Error(`Models 'large-v1', 'large-v2', 'large-v3' are not currently supported by the integrated Whisper engine due to model size restrictions of onnxruntime-node. To use large models, you can either select large-v3-turbo use the whisper.cpp engine instead.`);
1232
+ else if (platform === 'win32' && arch === 'arm64') {
1233
+ packageName = 'whisper.cpp-lib-windows-arm64-cpu';
1374
1234
  }
1375
- const packageName = modelNameToPackageName[modelName];
1376
- const modelDir = await loadPackage(packageName);
1377
- return { modelName, modelDir };
1378
- }
1379
- export function normalizeWhisperModelName(modelName, languageCode) {
1380
- if (languageCode !== 'en' && modelName.endsWith('.en')) {
1381
- const originalModelName = modelName;
1382
- modelName = modelName.slice(0, modelName.length - 3);
1383
- const logger = new Logger();
1384
- logger.logTitledMessage(`Warning`, `The model '${originalModelName}' is English only and cannot be used to transcribe language '${languageCode}'. Using '${modelName}' instead.`, chalk.yellowBright, 'warning');
1385
- }
1386
- return modelName;
1387
- }
1388
- export function isMultilingualModel(modelName) {
1389
- return !isEnglishOnlyModel(modelName);
1390
- }
1391
- export function isEnglishOnlyModel(modelName) {
1392
- return modelName.endsWith('.en');
1393
- }
1394
- export function getDefaultEncoderProvidersForModel(modelName) {
1395
- if (dmlProviderAvailable()) {
1396
- return ['dml', 'cpu'];
1235
+ else if (platform === 'darwin' && arch === 'x64') {
1236
+ if (useMacOsGpuBuildByDefault || enableGPU) {
1237
+ packageName = 'whisper.cpp-lib-macos-universal';
1238
+ }
1239
+ else {
1240
+ packageName = 'whisper.cpp-lib-macos-universal-cpu-basic';
1241
+ }
1397
1242
  }
1398
- else {
1399
- return [];
1243
+ else if (platform === 'darwin' && arch === 'arm64') {
1244
+ if (useMacOsGpuBuildByDefault || enableGPU) {
1245
+ packageName = 'whisper.cpp-lib-macos-universal';
1246
+ }
1247
+ else {
1248
+ packageName = 'whisper.cpp-lib-macos-universal-cpu-basic';
1249
+ }
1400
1250
  }
1401
- }
1402
- export function getDefaultDecoderProvidersForModel(modelName) {
1403
- if (modelName.startsWith('small') || modelName.startsWith('medium') || modelName.startsWith('large')) {
1404
- if (dmlProviderAvailable()) {
1405
- return ['dml', 'cpu'];
1251
+ else if (platform === 'linux' && arch === 'x64') {
1252
+ if (enableGPU) {
1253
+ packageName = 'whisper.cpp-lib-linux-x64-cublas-12.4.0';
1406
1254
  }
1407
1255
  else {
1408
- return [];
1256
+ packageName = 'whisper.cpp-lib-linux-x64-cpu';
1409
1257
  }
1410
1258
  }
1259
+ else if (platform === 'linux' && arch === 'arm64') {
1260
+ packageName = 'whisper.cpp-lib-linux-arm64-cpu';
1261
+ }
1411
1262
  else {
1412
- return [];
1263
+ throw new Error(`The platform and architecture combination ${platform} / ${arch} is not supported by the Whisper engine`);
1413
1264
  }
1265
+ const whisperCppLibPath = await loadPackage(packageName, callbacks);
1266
+ const libPath = whisperCppLibPath;
1267
+ return { libPath };
1414
1268
  }
1415
- export const modelNameToPackageName = {
1416
- 'tiny': 'whisper-tiny',
1417
- 'tiny.en': 'whisper-tiny.en',
1418
- 'base': 'whisper-base',
1419
- 'base.en': 'whisper-base.en',
1420
- 'small': 'whisper-small',
1421
- 'small.en': 'whisper-small.en',
1422
- 'medium': 'whisper-medium',
1423
- 'medium.en': 'whisper-medium.en',
1424
- 'large-v1': 'whisper-large-v1',
1425
- 'large-v2': 'whisper-large-v2',
1426
- 'large-v3': 'whisper-large-v3',
1427
- 'large-v3-turbo': 'whisper-large-v3-turbo-fp16',
1428
- };
1429
- export const tokenizerPackageName = 'whisper-tokenizer';
1269
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////
1270
+ // Tables
1271
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////
1430
1272
  const languageIdLookup = {
1431
1273
  'en': 0,
1432
1274
  'zh': 1,
@@ -1529,7 +1371,7 @@ const languageIdLookup = {
1529
1371
  'su': 98,
1530
1372
  //'yue': 99
1531
1373
  };
1532
- const alignmentHeadsIndexes = {
1374
+ const alignmentHeadsIndices = {
1533
1375
  'tiny': [14, 18, 20, 21, 22, 23,],
1534
1376
  'tiny.en': [6, 12, 17, 18, 19, 20, 21, 22,],
1535
1377
  'base': [25, 34, 35, 39, 41, 42, 44, 46,],
@@ -1543,7 +1385,7 @@ const alignmentHeadsIndexes = {
1543
1385
  'large-v3': [140, 217, 258, 272, 321, 354, 391, 424, 481, 506,],
1544
1386
  'large-v3-turbo': [44, 51, 63, 66, 71, 74,],
1545
1387
  };
1546
- const filterbanks_80 = [
1388
+ const melFilterbanks80 = [
1547
1389
  /* 0 */ { startIndex: 1, weights: [0.02486259490251541,] },
1548
1390
  /* 1 */ { startIndex: 1, weights: [0.001990821911022067, 0.022871771827340126,] },
1549
1391
  /* 2 */ { startIndex: 2, weights: [0.003981643822044134, 0.02088095061480999,] },
@@ -1625,7 +1467,7 @@ const filterbanks_80 = [
1625
1467
  /* 78 */ { startIndex: 179, weights: [0.0003849811910185963, 0.0008885387214832008, 0.001392096164636314, 0.0018956535495817661, 0.00239921105094254, 0.002902768552303314, 0.0034063260536640882, 0.003132763085886836, 0.0026481777895241976, 0.0021635922603309155, 0.0016790067311376333, 0.0011944210855290294, 0.0007098356145434082, 0.00022525011445395648,] },
1626
1468
  /* 79 */ { startIndex: 186, weights: [0.000366741674952209, 0.0008330700220540166, 0.0012993983691558242, 0.0017657268326729536, 0.0022320549469441175, 0.002698383294045925, 0.0031647118739783764, 0.003141313325613737, 0.002692554146051407, 0.0022437951993197203, 0.00179503601975739, 0.0013462770730257034, 0.000897518009878695, 0.0004487590049393475,] },
1627
1469
  ];
1628
- const filterbanks_128 = [
1470
+ const melFilterbank128 = [
1629
1471
  /* 0 */ { startIndex: 1, weights: [0.012373986653983593,] },
1630
1472
  /* 1 */ { startIndex: 1, weights: [0.030392564833164215,] },
1631
1473
  /* 2 */ { startIndex: 2, weights: [0.024747973307967186,] },
@@ -1755,9 +1597,38 @@ const filterbanks_128 = [
1755
1597
  /* 126 */ { startIndex: 187, weights: [0.0011469805613160133, 0.002344857668504119, 0.0035427347756922245, 0.004740611650049686, 0.0049519846215844154, 0.003782647429034114, 0.002613310469314456, 0.0014439737424254417, 0.0002746368118096143,] },
1756
1598
  /* 127 */ { startIndex: 191, weights: [0.0004756950947921723, 0.0016171716852113605, 0.002758648479357362, 0.0039001251570880413, 0.005041601601988077, 0.004457120783627033, 0.003342840587720275, 0.0022285603918135166, 0.0011142801959067583,] },
1757
1599
  ];
1600
+ const multilingualSpecialTokens = {
1601
+ endOfTextToken: 50257,
1602
+ startOfTextToken: 50258,
1603
+ languageTokensStart: 50259,
1604
+ languageTokensEnd: 50358,
1605
+ translateTaskToken: 50358,
1606
+ transcribeTaskToken: 50359,
1607
+ startOfPromptToken: 50361,
1608
+ nonSpeechToken: 50362,
1609
+ noTimestampsToken: 50363,
1610
+ timestampTokensStart: 50364,
1611
+ timestampTokensEnd: 50364 + 1501,
1612
+ };
1613
+ const englishOnlySpecialTokens = {
1614
+ endOfTextToken: 50256,
1615
+ startOfTextToken: 50257,
1616
+ languageTokensStart: 50258,
1617
+ languageTokensEnd: 50358,
1618
+ translateTaskToken: 50358,
1619
+ transcribeTaskToken: 50359,
1620
+ startOfPromptToken: 50360,
1621
+ nonSpeechToken: 50361,
1622
+ noTimestampsToken: 50362,
1623
+ timestampTokensStart: 50363,
1624
+ timestampTokensEnd: 50363 + 1501,
1625
+ };
1758
1626
  const largestMaximumTokensPerPart = 220;
1759
1627
  export const defaultWhisperOptions = {
1760
1628
  model: undefined,
1629
+ enableGPU: false,
1630
+ threadCount: 4,
1631
+ gpuDeviceIndex: 0,
1761
1632
  temperature: 0.1,
1762
1633
  prompt: undefined,
1763
1634
  topCandidateCount: 5,
@@ -1770,28 +1641,22 @@ export const defaultWhisperOptions = {
1770
1641
  endTokenThreshold: 0.9,
1771
1642
  includeEndTokenInCandidates: true,
1772
1643
  timestampAccuracy: undefined,
1773
- encoderProvider: undefined,
1774
- decoderProvider: undefined,
1775
1644
  seed: undefined,
1776
1645
  };
1777
1646
  export const defaultWhisperAlignmentOptions = {
1778
1647
  model: undefined,
1648
+ enableGPU: false,
1649
+ threadCount: 4,
1650
+ gpuDeviceIndex: 0,
1779
1651
  endTokenThreshold: 0.9,
1780
1652
  maxTokensPerPart: largestMaximumTokensPerPart,
1781
1653
  timestampAccuracy: undefined,
1782
- encoderProvider: undefined,
1783
- decoderProvider: undefined,
1784
1654
  };
1785
1655
  export const defaultWhisperLanguageDetectionOptions = {
1786
1656
  model: undefined,
1657
+ enableGPU: false,
1658
+ threadCount: 4,
1659
+ gpuDeviceIndex: 0,
1787
1660
  temperature: 1.0,
1788
- encoderProvider: undefined,
1789
- decoderProvider: undefined,
1790
- };
1791
- export const defaultWhisperVADOptions = {
1792
- model: undefined,
1793
- temperature: 1.0,
1794
- encoderProvider: undefined,
1795
- decoderProvider: undefined,
1796
1661
  };
1797
1662
  //# sourceMappingURL=WhisperSTT.js.map