echogarden 0.12.2 → 1.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 (334) hide show
  1. package/README.md +15 -14
  2. package/data/schemas/options.json +398 -111
  3. package/dist/alignment/DTWMfccSequenceAlignment.d.ts +1 -1
  4. package/dist/alignment/DTWMfccSequenceAlignment.js +8 -8
  5. package/dist/alignment/DTWSequenceAlignment.d.ts +1 -1
  6. package/dist/alignment/DTWSequenceAlignment.js +1 -1
  7. package/dist/alignment/DTWSequenceAlignmentWindowed.d.ts +1 -1
  8. package/dist/alignment/DTWSequenceAlignmentWindowed.js +2 -2
  9. package/dist/alignment/LevenshteinSequenceAlignment.d.ts +1 -1
  10. package/dist/alignment/LevenshteinSequenceAlignment.js +1 -1
  11. package/dist/alignment/SpeechAlignment.d.ts +9 -10
  12. package/dist/alignment/SpeechAlignment.js +136 -105
  13. package/dist/alignment/SpeechAlignment.js.map +1 -1
  14. package/dist/api/API.d.ts +13 -12
  15. package/dist/api/API.js +14 -13
  16. package/dist/api/API.js.map +1 -1
  17. package/dist/api/APIOptions.d.ts +5 -4
  18. package/dist/api/Alignment.d.ts +15 -9
  19. package/dist/api/Alignment.js +88 -74
  20. package/dist/api/Alignment.js.map +1 -1
  21. package/dist/api/Common.js +1 -1
  22. package/dist/api/Denoising.d.ts +6 -6
  23. package/dist/api/Denoising.js +23 -23
  24. package/dist/api/Denoising.js.map +1 -1
  25. package/dist/api/LanguageDetection.d.ts +19 -12
  26. package/dist/api/LanguageDetection.js +88 -38
  27. package/dist/api/LanguageDetection.js.map +1 -1
  28. package/dist/api/Recognition.d.ts +16 -6
  29. package/dist/api/Recognition.js +129 -55
  30. package/dist/api/Recognition.js.map +1 -1
  31. package/dist/api/SourceSeparation.d.ts +17 -0
  32. package/dist/api/SourceSeparation.js +61 -0
  33. package/dist/api/SourceSeparation.js.map +1 -0
  34. package/dist/api/Synthesis.d.ts +18 -18
  35. package/dist/api/Synthesis.js +191 -164
  36. package/dist/api/Synthesis.js.map +1 -1
  37. package/dist/api/Translation.d.ts +19 -8
  38. package/dist/api/Translation.js +132 -35
  39. package/dist/api/Translation.js.map +1 -1
  40. package/dist/api/Vad.d.ts +10 -5
  41. package/dist/api/Vad.js +76 -38
  42. package/dist/api/Vad.js.map +1 -1
  43. package/dist/audio/AudioBufferConversion.d.ts +1 -1
  44. package/dist/audio/AudioBufferConversion.js +4 -4
  45. package/dist/audio/AudioPlayer.d.ts +1 -1
  46. package/dist/audio/AudioPlayer.js +26 -26
  47. package/dist/audio/AudioPlayer.js.map +1 -1
  48. package/dist/audio/AudioRecorder.d.ts +1 -1
  49. package/dist/audio/AudioRecorder.js +5 -5
  50. package/dist/audio/AudioUtilities.d.ts +13 -9
  51. package/dist/audio/AudioUtilities.js +86 -24
  52. package/dist/audio/AudioUtilities.js.map +1 -1
  53. package/dist/cli/CLI.d.ts +3 -3
  54. package/dist/cli/CLI.js +271 -162
  55. package/dist/cli/CLI.js.map +1 -1
  56. package/dist/cli/CLIConfigFile.js +8 -8
  57. package/dist/cli/CLILauncher.js +6 -6
  58. package/dist/cli/CLIOptionsSchema.js +2 -2
  59. package/dist/cli/CLIParser.js +5 -5
  60. package/dist/cli/CLIStarter.js +4 -4
  61. package/dist/codecs/FFMpegTranscoder.d.ts +2 -2
  62. package/dist/codecs/FFMpegTranscoder.js +37 -37
  63. package/dist/codecs/FFMpegTranscoder.js.map +1 -1
  64. package/dist/codecs/TIMITCodec.js +5 -5
  65. package/dist/codecs/WaveCodec.d.ts +1 -1
  66. package/dist/codecs/WaveCodec.js +22 -22
  67. package/dist/denoising/RNNoise.d.ts +1 -1
  68. package/dist/denoising/RNNoise.js +9 -9
  69. package/dist/dsp/BiquadFilter.d.ts +3 -2
  70. package/dist/dsp/BiquadFilter.js +18 -11
  71. package/dist/dsp/BiquadFilter.js.map +1 -1
  72. package/dist/dsp/DecayingPeakEstimator.d.ts +16 -0
  73. package/dist/dsp/DecayingPeakEstimator.js +23 -0
  74. package/dist/dsp/DecayingPeakEstimator.js.map +1 -0
  75. package/dist/dsp/FFT.d.ts +8 -4
  76. package/dist/dsp/FFT.js +76 -30
  77. package/dist/dsp/FFT.js.map +1 -1
  78. package/dist/dsp/KWeightingFilter.d.ts +9 -0
  79. package/dist/dsp/KWeightingFilter.js +40 -0
  80. package/dist/dsp/KWeightingFilter.js.map +1 -0
  81. package/dist/dsp/LoudnessEstimator.d.ts +21 -0
  82. package/dist/dsp/LoudnessEstimator.js +47 -0
  83. package/dist/dsp/LoudnessEstimator.js.map +1 -0
  84. package/dist/dsp/MFCC.d.ts +2 -2
  85. package/dist/dsp/MFCC.js +15 -15
  86. package/dist/dsp/MelSpectogram.d.ts +1 -1
  87. package/dist/dsp/MelSpectogram.js +6 -6
  88. package/dist/dsp/Rubberband.d.ts +11 -11
  89. package/dist/dsp/Rubberband.js +27 -27
  90. package/dist/dsp/Sonic.d.ts +1 -1
  91. package/dist/dsp/Sonic.js +3 -3
  92. package/dist/dsp/SpeexResampler.d.ts +1 -1
  93. package/dist/dsp/SpeexResampler.js +2 -2
  94. package/dist/math/VectorMath.d.ts +12 -8
  95. package/dist/math/VectorMath.js +35 -32
  96. package/dist/math/VectorMath.js.map +1 -1
  97. package/dist/nlp/ChineseSegmentation.js +2 -2
  98. package/dist/nlp/CompromiseNLP.js +3 -3
  99. package/dist/nlp/EspeakPhonemizer.js +30 -30
  100. package/dist/nlp/IPA.js +20 -20
  101. package/dist/nlp/JapaneseSegmentation.js +6 -6
  102. package/dist/nlp/Lexicon.d.ts +1 -1
  103. package/dist/nlp/Lexicon.js +7 -7
  104. package/dist/nlp/Segmentation.d.ts +3 -0
  105. package/dist/nlp/Segmentation.js +21 -14
  106. package/dist/nlp/Segmentation.js.map +1 -1
  107. package/dist/nlp/TextNormalizer.js +16 -16
  108. package/dist/recognition/AmazonTranscribeSTT.d.ts +2 -2
  109. package/dist/recognition/AmazonTranscribeSTT.js +13 -14
  110. package/dist/recognition/AmazonTranscribeSTT.js.map +1 -1
  111. package/dist/recognition/AzureCognitiveServicesSTT.js +5 -6
  112. package/dist/recognition/AzureCognitiveServicesSTT.js.map +1 -1
  113. package/dist/recognition/GoogleCloudSTT.d.ts +3 -3
  114. package/dist/recognition/GoogleCloudSTT.js +18 -18
  115. package/dist/recognition/OpenAICloudSTT.d.ts +19 -0
  116. package/dist/recognition/OpenAICloudSTT.js +81 -0
  117. package/dist/recognition/OpenAICloudSTT.js.map +1 -0
  118. package/dist/recognition/SileroSTT.d.ts +2 -2
  119. package/dist/recognition/SileroSTT.js +25 -25
  120. package/dist/recognition/VoskSTT.d.ts +2 -2
  121. package/dist/recognition/VoskSTT.js +8 -8
  122. package/dist/recognition/WhisperCppSTT.d.ts +88 -0
  123. package/dist/recognition/WhisperCppSTT.js +332 -0
  124. package/dist/recognition/WhisperCppSTT.js.map +1 -0
  125. package/dist/recognition/WhisperSTT.d.ts +49 -25
  126. package/dist/recognition/WhisperSTT.js +626 -481
  127. package/dist/recognition/WhisperSTT.js.map +1 -1
  128. package/dist/server/Client.d.ts +1 -1
  129. package/dist/server/Client.js +22 -22
  130. package/dist/server/Server.js +9 -9
  131. package/dist/server/Server.js.map +1 -1
  132. package/dist/server/Worker.d.ts +22 -22
  133. package/dist/server/Worker.js +36 -36
  134. package/dist/server/Worker.js.map +1 -1
  135. package/dist/server/WorkerStarter.js +2 -2
  136. package/dist/source-separation/MDXNetSourceSeparation.d.ts +11 -0
  137. package/dist/source-separation/MDXNetSourceSeparation.js +161 -0
  138. package/dist/source-separation/MDXNetSourceSeparation.js.map +1 -0
  139. package/dist/speech-language-detection/SileroLanguageDetection.d.ts +1 -1
  140. package/dist/speech-language-detection/SileroLanguageDetection.js +7 -7
  141. package/dist/subtitles/Subtitles.d.ts +10 -0
  142. package/dist/subtitles/Subtitles.js +2 -2
  143. package/dist/subtitles/Subtitles.js.map +1 -1
  144. package/dist/synthesis/AwsPollyTTS.d.ts +1 -1
  145. package/dist/synthesis/AwsPollyTTS.js +12 -12
  146. package/dist/synthesis/AzureCognitiveServicesTTS.js +7 -7
  147. package/dist/synthesis/CoquiServerTTS.js +10 -10
  148. package/dist/synthesis/CoquiServerTTS.js.map +1 -1
  149. package/dist/synthesis/ElevenlabsTTS.d.ts +23 -0
  150. package/dist/synthesis/ElevenlabsTTS.js +103 -0
  151. package/dist/synthesis/ElevenlabsTTS.js.map +1 -0
  152. package/dist/synthesis/EspeakTTS.d.ts +6 -5
  153. package/dist/synthesis/EspeakTTS.js +81 -69
  154. package/dist/synthesis/EspeakTTS.js.map +1 -1
  155. package/dist/synthesis/FliteTTS.d.ts +3 -3
  156. package/dist/synthesis/FliteTTS.js +154 -154
  157. package/dist/synthesis/FliteTTS.js.map +1 -1
  158. package/dist/synthesis/GoogleCloudTTS.d.ts +3 -3
  159. package/dist/synthesis/GoogleCloudTTS.js +17 -17
  160. package/dist/synthesis/GoogleCloudTTS.js.map +1 -1
  161. package/dist/synthesis/GoogleTranslateTTS.d.ts +1 -1
  162. package/dist/synthesis/GoogleTranslateTTS.js +103 -103
  163. package/dist/synthesis/MicrosoftEdgeTTS.d.ts +2 -2
  164. package/dist/synthesis/MicrosoftEdgeTTS.js +74 -74
  165. package/dist/synthesis/OpenAICloudTTS.d.ts +13 -0
  166. package/dist/synthesis/OpenAICloudTTS.js +169 -0
  167. package/dist/synthesis/OpenAICloudTTS.js.map +1 -0
  168. package/dist/synthesis/SamTTS.js +3 -3
  169. package/dist/synthesis/SapiTTS.d.ts +3 -3
  170. package/dist/synthesis/SapiTTS.js +26 -26
  171. package/dist/synthesis/StreamlabsPollyTTS.d.ts +2 -2
  172. package/dist/synthesis/StreamlabsPollyTTS.js +27 -27
  173. package/dist/synthesis/SvoxPicoTTS.d.ts +2 -2
  174. package/dist/synthesis/SvoxPicoTTS.js +65 -65
  175. package/dist/synthesis/SvoxPicoTTS.js.map +1 -1
  176. package/dist/synthesis/VitsTTS.d.ts +3 -3
  177. package/dist/synthesis/VitsTTS.js +378 -378
  178. package/dist/synthesis/VitsTTS.js.map +1 -1
  179. package/dist/tests/Test.js +2 -2
  180. package/dist/utilities/Compression.d.ts +5 -0
  181. package/dist/utilities/Compression.js +29 -13
  182. package/dist/utilities/Compression.js.map +1 -1
  183. package/dist/utilities/FileDownloader.d.ts +1 -1
  184. package/dist/utilities/FileDownloader.js +16 -16
  185. package/dist/utilities/FileSystem.js +7 -7
  186. package/dist/utilities/Locale.d.ts +7 -7
  187. package/dist/utilities/Locale.js +15 -15
  188. package/dist/utilities/Logger.js +3 -3
  189. package/dist/utilities/ObjectUtilities.js +19 -19
  190. package/dist/utilities/OpenPromise.js +2 -2
  191. package/dist/utilities/OpenPromise.js.map +1 -1
  192. package/dist/utilities/PackageManager.js +31 -0
  193. package/dist/utilities/PackageManager.js.map +1 -1
  194. package/dist/utilities/PathUtilities.js +8 -8
  195. package/dist/utilities/RandomGenerator.js +2 -2
  196. package/dist/utilities/SmoothEstimator.d.ts +8 -0
  197. package/dist/utilities/SmoothEstimator.js +25 -0
  198. package/dist/utilities/SmoothEstimator.js.map +1 -0
  199. package/dist/utilities/TarballMaker.js +8 -8
  200. package/dist/utilities/Timeline.d.ts +3 -2
  201. package/dist/utilities/Timeline.js +11 -11
  202. package/dist/utilities/Timeline.js.map +1 -1
  203. package/dist/utilities/Timer.js +4 -4
  204. package/dist/utilities/Utilities.d.ts +4 -0
  205. package/dist/utilities/Utilities.js +38 -15
  206. package/dist/utilities/Utilities.js.map +1 -1
  207. package/dist/utilities/WasmMemoryManager.js +7 -7
  208. package/dist/utilities/WebReader.js +23 -23
  209. package/dist/utilities/WikipediaReader.js +2 -2
  210. package/dist/voice-activity-detection/AdaptiveGateVAD.d.ts +28 -0
  211. package/dist/voice-activity-detection/AdaptiveGateVAD.js +138 -0
  212. package/dist/voice-activity-detection/AdaptiveGateVAD.js.map +1 -0
  213. package/dist/voice-activity-detection/SileroVAD.d.ts +1 -1
  214. package/dist/voice-activity-detection/SileroVAD.js +5 -5
  215. package/dist/voice-activity-detection/SileroVAD.js.map +1 -1
  216. package/dist/voice-activity-detection/WebRtcVAD.d.ts +1 -1
  217. package/dist/voice-activity-detection/WebRtcVAD.js +4 -4
  218. package/docs/API.md +29 -11
  219. package/docs/CLI.md +31 -7
  220. package/docs/Contributing.md +38 -0
  221. package/docs/Development.md +93 -19
  222. package/docs/Engines.md +28 -16
  223. package/docs/Licenses.md +4 -1
  224. package/docs/Options.md +158 -78
  225. package/docs/Releases.md +262 -0
  226. package/docs/Server.md +7 -7
  227. package/docs/Tasklist.md +95 -76
  228. package/docs/Technical.md +4 -4
  229. package/package.json +13 -14
  230. package/src/alignment/DTWMfccSequenceAlignment.ts +9 -9
  231. package/src/alignment/DTWSequenceAlignment.ts +2 -2
  232. package/src/alignment/DTWSequenceAlignmentWindowed.ts +3 -3
  233. package/src/alignment/LevenshteinSequenceAlignment.ts +2 -2
  234. package/src/alignment/SpeechAlignment.ts +204 -119
  235. package/src/api/API.ts +14 -13
  236. package/src/api/APIOptions.ts +12 -11
  237. package/src/api/Alignment.ts +147 -90
  238. package/src/api/Common.ts +1 -1
  239. package/src/api/Denoising.ts +28 -28
  240. package/src/api/LanguageDetection.ts +135 -48
  241. package/src/api/Recognition.ts +198 -59
  242. package/src/api/SourceSeparation.ts +99 -0
  243. package/src/api/Synthesis.ts +217 -181
  244. package/src/api/Translation.ts +193 -40
  245. package/src/api/Vad.ts +110 -41
  246. package/src/audio/AudioBufferConversion.ts +4 -4
  247. package/src/audio/AudioPlayer.ts +27 -27
  248. package/src/audio/AudioRecorder.ts +5 -5
  249. package/src/audio/AudioUtilities.ts +107 -24
  250. package/src/cli/CLI.ts +313 -164
  251. package/src/cli/CLIConfigFile.ts +8 -8
  252. package/src/cli/CLILauncher.ts +6 -6
  253. package/src/cli/CLIOptionsSchema.ts +2 -2
  254. package/src/cli/CLIParser.ts +5 -5
  255. package/src/cli/CLIStarter.ts +4 -4
  256. package/src/codecs/FFMpegTranscoder.ts +38 -38
  257. package/src/codecs/TIMITCodec.ts +5 -5
  258. package/src/codecs/WaveCodec.ts +22 -22
  259. package/src/denoising/RNNoise.ts +9 -9
  260. package/src/dsp/BiquadFilter.ts +19 -11
  261. package/src/dsp/DecayingPeakEstimator.ts +35 -0
  262. package/src/dsp/FFT.ts +103 -35
  263. package/src/dsp/KWeightingFilter.ts +43 -0
  264. package/src/dsp/LoudnessEstimator.ts +74 -0
  265. package/src/dsp/MFCC.ts +15 -15
  266. package/src/dsp/MelSpectogram.ts +7 -7
  267. package/src/dsp/Rubberband.ts +38 -38
  268. package/src/dsp/Sonic.ts +4 -4
  269. package/src/dsp/SpeexResampler.ts +2 -2
  270. package/src/math/VectorMath.ts +42 -33
  271. package/src/nlp/ChineseSegmentation.ts +3 -3
  272. package/src/nlp/CompromiseNLP.ts +3 -3
  273. package/src/nlp/EspeakPhonemizer.ts +30 -30
  274. package/src/nlp/IPA.ts +20 -20
  275. package/src/nlp/JapaneseSegmentation.ts +6 -6
  276. package/src/nlp/Lexicon.ts +8 -8
  277. package/src/nlp/Segmentation.ts +23 -14
  278. package/src/nlp/TextNormalizer.ts +16 -16
  279. package/src/recognition/AmazonTranscribeSTT.ts +16 -17
  280. package/src/recognition/AzureCognitiveServicesSTT.ts +8 -6
  281. package/src/recognition/GoogleCloudSTT.ts +21 -21
  282. package/src/recognition/OpenAICloudSTT.ts +142 -0
  283. package/src/recognition/SileroSTT.ts +26 -26
  284. package/src/recognition/VoskSTT.ts +10 -10
  285. package/src/recognition/WhisperCppSTT.ts +555 -0
  286. package/src/recognition/WhisperSTT.ts +760 -507
  287. package/src/server/Client.ts +23 -23
  288. package/src/server/Server.ts +9 -9
  289. package/src/server/Worker.ts +53 -53
  290. package/src/server/WorkerStarter.ts +2 -2
  291. package/src/source-separation/MDXNetSourceSeparation.ts +228 -0
  292. package/src/speech-language-detection/SileroLanguageDetection.ts +8 -8
  293. package/src/subtitles/Subtitles.ts +3 -3
  294. package/src/synthesis/AwsPollyTTS.ts +14 -14
  295. package/src/synthesis/AzureCognitiveServicesTTS.ts +10 -10
  296. package/src/synthesis/CoquiServerTTS.ts +10 -10
  297. package/src/synthesis/ElevenlabsTTS.ts +137 -0
  298. package/src/synthesis/EspeakTTS.ts +90 -71
  299. package/src/synthesis/FliteTTS.ts +157 -157
  300. package/src/synthesis/GoogleCloudTTS.ts +19 -19
  301. package/src/synthesis/GoogleTranslateTTS.ts +104 -104
  302. package/src/synthesis/MicrosoftEdgeTTS.ts +80 -80
  303. package/src/synthesis/OpenAICloudTTS.ts +196 -0
  304. package/src/synthesis/SamTTS.ts +3 -3
  305. package/src/synthesis/SapiTTS.ts +29 -29
  306. package/src/synthesis/StreamlabsPollyTTS.ts +29 -29
  307. package/src/synthesis/SvoxPicoTTS.ts +67 -67
  308. package/src/synthesis/VitsTTS.ts +380 -380
  309. package/src/tests/Test.ts +4 -4
  310. package/src/utilities/Compression.ts +34 -13
  311. package/src/utilities/FileDownloader.ts +19 -19
  312. package/src/utilities/FileSystem.ts +7 -7
  313. package/src/utilities/Locale.ts +22 -22
  314. package/src/utilities/Logger.ts +4 -4
  315. package/src/utilities/ObjectUtilities.ts +19 -19
  316. package/src/utilities/OpenPromise.ts +2 -2
  317. package/src/utilities/PackageManager.ts +40 -0
  318. package/src/utilities/PathUtilities.ts +8 -8
  319. package/src/utilities/RandomGenerator.ts +3 -3
  320. package/src/utilities/SmoothEstimator.ts +35 -0
  321. package/src/utilities/TarballMaker.ts +9 -9
  322. package/src/utilities/Timeline.ts +15 -13
  323. package/src/utilities/Timer.ts +4 -4
  324. package/src/utilities/Utilities.ts +49 -15
  325. package/src/utilities/WasmMemoryManager.ts +7 -7
  326. package/src/utilities/WebReader.ts +23 -23
  327. package/src/utilities/WikipediaReader.ts +2 -2
  328. package/src/voice-activity-detection/AdaptiveGateVAD.ts +202 -0
  329. package/src/voice-activity-detection/SileroVAD.ts +5 -5
  330. package/src/voice-activity-detection/WebRtcVAD.ts +5 -5
  331. package/dist/synthesis/ElevenLabsTTS.d.ts +0 -8
  332. package/dist/synthesis/ElevenLabsTTS.js +0 -82
  333. package/dist/synthesis/ElevenLabsTTS.js.map +0 -1
  334. package/src/synthesis/ElevenLabsTTS.ts +0 -104
@@ -1,36 +1,61 @@
1
- import { extendDeep } from "../utilities/ObjectUtilities.js"
2
-
3
- import { logToStderr } from "../utilities/Utilities.js"
4
- import { AudioSourceParam, RawAudio, downmixToMonoAndNormalize, ensureRawAudio, getRawAudioDuration, normalizeAudioLevel, trimAudioEnd } from "../audio/AudioUtilities.js"
5
- import { Logger } from "../utilities/Logger.js"
6
- import { resampleAudioSpeex } from "../dsp/SpeexResampler.js"
7
-
8
- import * as API from "./API.js"
9
- import { Timeline, addTimeOffsetToTimeline, addWordTextOffsetsToTimeline, wordTimelineToSegmentSentenceTimeline } from "../utilities/Timeline.js"
10
- import { formatLanguageCodeWithName, getDefaultDialectForLanguageCodeIfPossible, getShortLanguageCode, normalizeLanguageCode } from "../utilities/Locale.js"
11
- import { WhisperOptions, whisperOptionsDefaults } from "../recognition/WhisperSTT.js"
12
- import chalk from "chalk"
13
- import { DtwGranularity } from "../alignment/SpeechAlignment.js"
14
- import { SubtitlesConfig, defaultSubtitlesBaseConfig } from "../subtitles/Subtitles.js"
15
- import { synthesize } from "./API.js"
16
- import { EspeakOptions, defaultEspeakOptions } from "../synthesis/EspeakTTS.js"
1
+ import { extendDeep } from '../utilities/ObjectUtilities.js'
2
+
3
+ import { logToStderr } from '../utilities/Utilities.js'
4
+ import { AudioSourceParam, RawAudio, ensureRawAudio, getRawAudioDuration, normalizeAudioLevel, trimAudioEnd } from '../audio/AudioUtilities.js'
5
+ import { Logger } from '../utilities/Logger.js'
6
+
7
+ import * as API from './API.js'
8
+ import { Timeline, addTimeOffsetToTimeline, addWordTextOffsetsToTimeline, wordTimelineToSegmentSentenceTimeline } from '../utilities/Timeline.js'
9
+ import { formatLanguageCodeWithName, getDefaultDialectForLanguageCodeIfPossible, getShortLanguageCode, normalizeLanguageCode } from '../utilities/Locale.js'
10
+ import { WhisperOptions } from '../recognition/WhisperSTT.js'
11
+ import chalk from 'chalk'
12
+ import { DtwGranularity, createAlignmentReferenceUsingEspeak } from '../alignment/SpeechAlignment.js'
13
+ import { SubtitlesConfig, defaultSubtitlesBaseConfig } from '../subtitles/Subtitles.js'
14
+
17
15
 
18
16
  const log = logToStderr
19
17
 
20
18
  export async function align(input: AudioSourceParam, transcript: string, options: AlignmentOptions): Promise<AlignmentResult> {
21
19
  const logger = new Logger()
20
+
22
21
  const startTimestamp = logger.getTimestamp()
23
22
 
24
- logger.start("Prepare for alignment")
23
+ options = extendDeep(defaultAlignmentOptions, options)
25
24
 
26
25
  const inputRawAudio = await ensureRawAudio(input)
27
26
 
28
- let sourceRawAudio = await ensureRawAudio(inputRawAudio, 16000, 1)
27
+ let sourceRawAudio: RawAudio
28
+ let isolatedRawAudio: RawAudio | undefined
29
+ let backgroundRawAudio: RawAudio | undefined
30
+
31
+ if (options.isolate) {
32
+ logger.log(``)
33
+ logger.end();
34
+
35
+ ({ isolatedRawAudio, backgroundRawAudio } = await API.isolate(inputRawAudio, options.sourceSeparation!))
36
+
37
+ logger.end()
38
+ logger.log(``)
39
+
40
+ sourceRawAudio = await ensureRawAudio(isolatedRawAudio, 16000, 1)
41
+ } else {
42
+ sourceRawAudio = await ensureRawAudio(inputRawAudio, 16000, 1)
43
+ }
44
+
45
+ let sourceUncropTimeline: Timeline | undefined
46
+
47
+ if (options.crop) {
48
+ logger.start('Crop using voice activity detection');
49
+ ({ timeline: sourceUncropTimeline, croppedRawAudio: sourceRawAudio } = await API.detectVoiceActivity(sourceRawAudio, options.vad!))
50
+
51
+ logger.end()
52
+ }
53
+
54
+ logger.start('Prepare for alignment')
55
+
29
56
  sourceRawAudio = normalizeAudioLevel(sourceRawAudio)
30
57
  sourceRawAudio.audioChannels[0] = trimAudioEnd(sourceRawAudio.audioChannels[0])
31
58
 
32
- options = extendDeep(defaultAlignmentOptions, options)
33
-
34
59
  if (options.dtw!.windowDuration == null) {
35
60
  const sourceAudioDuration = getRawAudioDuration(sourceRawAudio)
36
61
 
@@ -48,7 +73,7 @@ export async function align(input: AudioSourceParam, transcript: string, options
48
73
  if (options.language) {
49
74
  language = normalizeLanguageCode(options.language!)
50
75
  } else {
51
- logger.start("No language specified. Detecting language")
76
+ logger.start('No language specified. Detecting language')
52
77
  const { detectedLanguage } = await API.detectTextLanguage(transcript, options.languageDetection || {})
53
78
  language = detectedLanguage
54
79
 
@@ -58,34 +83,9 @@ export async function align(input: AudioSourceParam, transcript: string, options
58
83
 
59
84
  language = getDefaultDialectForLanguageCodeIfPossible(language)
60
85
 
61
- logger.start("Load alignment module")
62
-
63
- const { alignUsingDtwWithRecognition, alignUsingDtw } = await import("../alignment/SpeechAlignment.js")
86
+ logger.start('Load alignment module')
64
87
 
65
- async function getAlignmentReference() {
66
- logger.start("Create alignment reference with eSpeak")
67
-
68
- const synthesisOptions: API.SynthesisOptions = {
69
- engine: "espeak",
70
- language,
71
- plainText: options.plainText,
72
- customLexiconPaths: options.customLexiconPaths,
73
-
74
- espeak: {
75
- useKlatt: false
76
- }
77
- }
78
-
79
- let { audio: referenceRawAudio, timeline: segmentTimeline, voice: espeakVoice } = await synthesize(transcript, synthesisOptions)
80
-
81
- const sentenceTimeline = segmentTimeline.flatMap(entry => entry.timeline!)
82
- const wordTimeline = sentenceTimeline.flatMap(entry => entry.timeline!)
83
-
84
- referenceRawAudio = await resampleAudioSpeex(referenceRawAudio as RawAudio, 16000)
85
- referenceRawAudio = downmixToMonoAndNormalize(referenceRawAudio)
86
-
87
- return { referenceRawAudio, referenceTimeline: wordTimeline, espeakVoice }
88
- }
88
+ const { alignUsingDtwWithRecognition: alignUsingDtwWithRecognitionReference, alignUsingDtw } = await import('../alignment/SpeechAlignment.js')
89
89
 
90
90
  function getDtwWindowDurationsAndGranularities() {
91
91
  let granularities: DtwGranularity[]
@@ -123,8 +123,12 @@ export async function align(input: AudioSourceParam, transcript: string, options
123
123
  let mappedTimeline: Timeline
124
124
 
125
125
  switch (options.engine) {
126
- case "dtw": {
127
- const { referenceRawAudio, referenceTimeline } = await getAlignmentReference()
126
+ case 'dtw': {
127
+ const {
128
+ referenceRawAudio,
129
+ referenceTimeline
130
+ } = await createAlignmentReferenceUsingEspeak(transcript, language, options.plainText, options.customLexiconPaths)
131
+
128
132
  logger.end()
129
133
 
130
134
  const { windowDurations, granularities } = getDtwWindowDurationsAndGranularities()
@@ -134,62 +138,70 @@ export async function align(input: AudioSourceParam, transcript: string, options
134
138
  break
135
139
  }
136
140
 
137
- case "dtw-ra": {
138
- /*
139
- const promptWords = (await splitToWords(prompt, language)).filter(word => isWord(word))
141
+ case 'dtw-ra': {
142
+ const recognitionOptions: API.RecognitionOptions =
143
+ extendDeep({ crop: options.crop, language }, options.recognition)
140
144
 
141
- shuffleArrayInPlace(promptWords, this.randomGen)
142
- //promptWords.reverse()
145
+ logger.end()
143
146
 
144
- prompt = promptWords.join(" ")
145
- */
147
+ // Recognize source audio
148
+ const { transcript: recognizedTranscript, wordTimeline: recognitionTimeline } = await API.recognize(sourceRawAudio, recognitionOptions)
146
149
 
147
- const recognitionOptionsDefaults: API.RecognitionOptions = {
148
- engine: "whisper",
149
- language,
150
- }
150
+ // Synthesize the ground-truth transcript and get its timeline
151
+ logger.start('Synthesize ground-truth transcript with eSpeak')
151
152
 
152
- const recognitionOptions: API.RecognitionOptions = extendDeep(recognitionOptionsDefaults, options.recognition || {})
153
+ const {
154
+ referenceRawAudio,
155
+ referenceTimeline,
156
+ } = await createAlignmentReferenceUsingEspeak(transcript, language, options.plainText, options.customLexiconPaths, true)
153
157
 
154
- logger.end()
155
-
156
- const { wordTimeline: recognitionTimeline } = await API.recognize(sourceRawAudio, recognitionOptions)
158
+ // Synthesize the recognized transcript and get its timeline
159
+ logger.start('Synthesize recognized transcript with eSpeak')
157
160
 
158
- const { referenceRawAudio, referenceTimeline, espeakVoice } = await getAlignmentReference()
161
+ const {
162
+ referenceRawAudio: synthesizedRecognizedTranscriptRawAudio,
163
+ referenceTimeline: synthesizedRecognitionTimeline
164
+ } = await createAlignmentReferenceUsingEspeak(recognizedTranscript, language, undefined, undefined, true)
159
165
 
160
166
  logger.end()
161
167
 
162
168
  const { windowDurations, granularities } = getDtwWindowDurationsAndGranularities()
163
169
 
164
- const espeakOptions: EspeakOptions = { ...defaultEspeakOptions, voice: espeakVoice, useKlatt: false }
165
-
166
170
  const phoneAlignmentMethod = options.dtw!.phoneAlignmentMethod!
167
171
 
168
- mappedTimeline = await alignUsingDtwWithRecognition(sourceRawAudio, referenceRawAudio, referenceTimeline, recognitionTimeline, granularities, windowDurations, espeakOptions, phoneAlignmentMethod)
172
+ // Align the ground-truth transcript and the recognized transcript
173
+ mappedTimeline = await alignUsingDtwWithRecognitionReference(
174
+ sourceRawAudio,
175
+ referenceRawAudio,
176
+ referenceTimeline,
177
+
178
+ recognitionTimeline,
179
+ synthesizedRecognizedTranscriptRawAudio,
180
+ synthesizedRecognitionTimeline,
181
+
182
+ granularities,
183
+ windowDurations,
184
+ phoneAlignmentMethod)
169
185
 
170
186
  break
171
187
  }
172
188
 
173
- case "whisper": {
174
- const WhisperSTT = await import("../recognition/WhisperSTT.js")
189
+ case 'whisper': {
190
+ const WhisperSTT = await import('../recognition/WhisperSTT.js')
175
191
 
176
192
  const whisperOptions = options.whisper!
177
193
 
178
194
  const shortLanguageCode = getShortLanguageCode(language)
179
195
 
180
- const { modelName, modelDir, tokenizerDir } = await WhisperSTT.loadPackagesAndGetPaths(whisperOptions.model, language)
181
-
182
- if (modelName.endsWith(".en") && shortLanguageCode != "en") {
183
- throw new Error(`The model '${modelName}' is English only and cannot transcribe language '${shortLanguageCode}'`)
184
- }
196
+ const { modelName, modelDir } = await WhisperSTT.loadPackagesAndGetPaths(whisperOptions.model, language)
185
197
 
186
198
  if (getRawAudioDuration(sourceRawAudio) > 30) {
187
- throw new Error("Whisper based alignment currently only supports audio inputs that are 30s or less")
199
+ throw new Error('Whisper based alignment currently only supports audio inputs that are 30s or less')
188
200
  }
189
201
 
190
202
  logger.end()
191
203
 
192
- mappedTimeline = await WhisperSTT.align(sourceRawAudio, transcript, modelName, modelDir, tokenizerDir, shortLanguageCode)
204
+ mappedTimeline = await WhisperSTT.align(sourceRawAudio, transcript, modelName, modelDir, shortLanguageCode)
193
205
 
194
206
  break
195
207
  }
@@ -199,8 +211,15 @@ export async function align(input: AudioSourceParam, transcript: string, options
199
211
  }
200
212
  }
201
213
 
214
+ // If the audio was cropped before recognition, map the timestamps back to the original audio
215
+ if (sourceUncropTimeline && sourceUncropTimeline.length > 0) {
216
+ API.convertCroppedToUncroppedTimeline(mappedTimeline, sourceUncropTimeline)
217
+ }
218
+
219
+ // Add text offsets
202
220
  addWordTextOffsetsToTimeline(mappedTimeline, transcript)
203
221
 
222
+ // Make segment timeline
204
223
  const { segmentTimeline } = await wordTimelineToSegmentSentenceTimeline(mappedTimeline, transcript, language, options.plainText?.paragraphBreaks, options.plainText?.whitespace)
205
224
 
206
225
  logger.end()
@@ -209,9 +228,13 @@ export async function align(input: AudioSourceParam, transcript: string, options
209
228
  return {
210
229
  timeline: segmentTimeline,
211
230
  wordTimeline: mappedTimeline,
212
- inputRawAudio,
231
+
213
232
  transcript,
214
- language
233
+ language,
234
+
235
+ inputRawAudio,
236
+ isolatedRawAudio,
237
+ backgroundRawAudio,
215
238
  }
216
239
  }
217
240
 
@@ -246,23 +269,33 @@ export async function alignSegments(sourceRawAudio: RawAudio, segmentTimeline: T
246
269
  export interface AlignmentResult {
247
270
  timeline: Timeline
248
271
  wordTimeline: Timeline
272
+
249
273
  transcript: string
250
274
  language: string
275
+
251
276
  inputRawAudio: RawAudio
277
+ isolatedRawAudio?: RawAudio
278
+ backgroundRawAudio?: RawAudio
252
279
  }
253
280
 
254
- export type AlignmentEngine = "dtw" | "dtw-ra" | "whisper"
255
- export type PhoneAlignmentMethod = "interpolation" | "dtw"
281
+ export type AlignmentEngine = 'dtw' | 'dtw-ra' | 'whisper'
282
+ export type PhoneAlignmentMethod = 'interpolation' | 'dtw'
256
283
 
257
284
  export interface AlignmentOptions {
258
285
  engine?: AlignmentEngine
259
286
 
260
287
  language?: string
261
288
 
262
- languageDetection?: API.TextLanguageDetectionOptions
289
+ isolate?: boolean
290
+
291
+ crop?: boolean
263
292
 
264
293
  customLexiconPaths?: string[]
265
294
 
295
+ languageDetection?: API.TextLanguageDetectionOptions
296
+
297
+ vad?: API.VADOptions
298
+
266
299
  plainText?: API.PlainTextOptions
267
300
 
268
301
  subtitles?: SubtitlesConfig
@@ -275,19 +308,25 @@ export interface AlignmentOptions {
275
308
 
276
309
  recognition?: API.RecognitionOptions
277
310
 
311
+ sourceSeparation?: API.SourceSeparationOptions
312
+
278
313
  whisper?: WhisperOptions
279
314
  }
280
315
 
281
316
  export const defaultAlignmentOptions: AlignmentOptions = {
282
- engine: "dtw",
317
+ engine: 'dtw',
283
318
 
284
319
  language: undefined,
285
320
 
286
- languageDetection: {
287
- },
321
+ isolate: false,
322
+
323
+ crop: true,
288
324
 
289
325
  customLexiconPaths: undefined,
290
326
 
327
+ languageDetection: {
328
+ },
329
+
291
330
  plainText: {
292
331
  paragraphBreaks: 'double',
293
332
  whitespace: 'collapse'
@@ -302,28 +341,46 @@ export const defaultAlignmentOptions: AlignmentOptions = {
302
341
  },
303
342
 
304
343
  recognition: {
344
+ whisper: {
345
+ temperature: 0.15,
346
+ topCandidateCount: 5,
347
+ punctuationThreshold: 0.2,
348
+ maxTokensPerPart: 250,
349
+ autoPromptParts: true,
350
+ suppressRepetition: true,
351
+ seed: undefined,
352
+ decodeTimestampTokens: false,
353
+ }
354
+ },
355
+
356
+ vad: {
357
+ engine: 'adaptive-gate'
358
+ },
359
+
360
+ sourceSeparation: {
305
361
  },
306
362
 
307
- whisper: whisperOptionsDefaults
363
+ whisper: {
364
+ }
308
365
  }
309
366
 
310
367
  export const alignmentEngines: API.EngineMetadata[] = [
311
368
  {
312
369
  id: 'dtw',
313
370
  name: 'Dynamic Time Warping',
314
- description: 'Makes use of synthesis to find the best mapping between the original audio and its transcript.',
371
+ description: 'Makes use of a synthesized reference to find the best mapping between the spoken audio and its transcript.',
315
372
  type: 'local'
316
373
  },
317
374
  {
318
375
  id: 'dtw-ra',
319
376
  name: 'Dynamic Time Warping with Recognition Assist',
320
- description: 'Makes use of both synthesis and recognition to find the best mapping between the original audio and its transcript.',
377
+ description: 'Makes use of both a synthesized reference and a synthsized recognized transcript to find the best mapping between the spoken audio and its transcript.',
321
378
  type: 'local'
322
379
  },
323
380
  {
324
381
  id: 'whisper',
325
382
  name: 'OpenAI Whisper',
326
- description: 'Extracts timestamps from the internal state of the Whisper recognition model (note: currently limited to a maximum of 30s audio length).',
383
+ description: 'Extracts timestamps from the internal state of the Whisper recognition model (note: currently limited to a maximum audio duration of 30 seconds).',
327
384
  type: 'local'
328
385
  }
329
386
  ]
package/src/api/Common.ts CHANGED
@@ -1,4 +1,4 @@
1
- export const appName = "echogarden"
1
+ export const appName = 'echogarden'
2
2
 
3
3
  export interface EngineMetadata {
4
4
  id: string
@@ -1,12 +1,12 @@
1
- import { extendDeep } from "../utilities/ObjectUtilities.js"
1
+ import { extendDeep } from '../utilities/ObjectUtilities.js'
2
2
 
3
- import { AudioSourceParam, RawAudio, applyGainDecibels, ensureRawAudio, getAudioPeakDecibels, mixAudio, normalizeAudioLevel } from "../audio/AudioUtilities.js"
4
- import { Logger } from "../utilities/Logger.js"
3
+ import { AudioSourceParam, RawAudio, applyGainDecibels, ensureRawAudio, getSamplePeakDecibels, mixAudio, normalizeAudioLevel } from '../audio/AudioUtilities.js'
4
+ import { Logger } from '../utilities/Logger.js'
5
5
 
6
- import { logToStderr } from "../utilities/Utilities.js"
7
- import { resampleAudioSpeex } from "../dsp/SpeexResampler.js"
8
- import { EngineMetadata } from "./Common.js"
9
- import chalk from "chalk"
6
+ import { logToStderr } from '../utilities/Utilities.js'
7
+ import { resampleAudioSpeex } from '../dsp/SpeexResampler.js'
8
+ import { EngineMetadata } from './Common.js'
9
+ import chalk from 'chalk'
10
10
 
11
11
  const log = logToStderr
12
12
 
@@ -14,7 +14,7 @@ export async function denoise(input: AudioSourceParam, options: DenoisingOptions
14
14
  const logger = new Logger()
15
15
  const startTime = logger.getTimestamp()
16
16
 
17
- logger.start("Prepare for denoising")
17
+ logger.start('Prepare for denoising')
18
18
 
19
19
  options = extendDeep(defaultDenoisingOptions, options)
20
20
 
@@ -30,8 +30,8 @@ export async function denoise(input: AudioSourceParam, options: DenoisingOptions
30
30
  let denoisedAudio: RawAudio
31
31
 
32
32
  switch (options.method) {
33
- case "rnnoise": {
34
- const RNNoise = await import("../denoising/RNNoise.js")
33
+ case 'rnnoise': {
34
+ const RNNoise = await import('../denoising/RNNoise.js')
35
35
  logger.end()
36
36
 
37
37
  const denoisedAudioChannels: Float32Array[] = []
@@ -53,27 +53,27 @@ export async function denoise(input: AudioSourceParam, options: DenoisingOptions
53
53
  }
54
54
  }
55
55
 
56
- logger.start("Postprocess audio")
56
+ logger.start('Postprocess audio')
57
57
 
58
58
  const shouldNormalize = options.postProcessing!.normalizeAudio!
59
- const targetPeakDb = options.postProcessing!.targetPeakDb!
60
- const maxIncreaseDb = options.postProcessing!.maxIncreaseDb!
61
- const dryMixGainDb = options.postProcessing!.dryMixGainDb!
59
+ const targetPeakDecibels = options.postProcessing!.targetPeak!
60
+ const maxGainIncreaseDecibels = options.postProcessing!.maxGainIncrease!
61
+ const dryMixGainDecibels = options.postProcessing!.dryMixGain!
62
62
 
63
- const preMixPeakDb = getAudioPeakDecibels(denoisedAudio.audioChannels)
64
- denoisedAudio = mixAudio(denoisedAudio, applyGainDecibels(resampledRawAudio, dryMixGainDb))
65
- const postMixPeakDb = getAudioPeakDecibels(denoisedAudio.audioChannels)
63
+ const preMixPeakDecibels = getSamplePeakDecibels(denoisedAudio.audioChannels)
64
+ denoisedAudio = mixAudio(denoisedAudio, applyGainDecibels(resampledRawAudio, dryMixGainDecibels))
65
+ const postMixPeakDecibels = getSamplePeakDecibels(denoisedAudio.audioChannels)
66
66
 
67
67
  if (shouldNormalize) {
68
- denoisedAudio = normalizeAudioLevel(denoisedAudio, targetPeakDb, maxIncreaseDb)
68
+ denoisedAudio = normalizeAudioLevel(denoisedAudio, targetPeakDecibels, maxGainIncreaseDecibels)
69
69
  } else {
70
- denoisedAudio = applyGainDecibels(denoisedAudio, preMixPeakDb - postMixPeakDb)
70
+ denoisedAudio = applyGainDecibels(denoisedAudio, preMixPeakDecibels - postMixPeakDecibels)
71
71
  }
72
72
 
73
73
  logger.end()
74
74
 
75
75
  logger.log('')
76
- logger.logDuration("Total denoising time", startTime, chalk.magentaBright)
76
+ logger.logDuration('Total denoising time', startTime, chalk.magentaBright)
77
77
 
78
78
  return {
79
79
  denoisedAudio,
@@ -86,27 +86,27 @@ export interface DenoisingResult {
86
86
  inputRawAudio: RawAudio
87
87
  }
88
88
 
89
- export type DenoisingMethod = "rnnoise"
89
+ export type DenoisingMethod = 'rnnoise'
90
90
 
91
91
  export interface DenoisingOptions {
92
92
  method?: DenoisingMethod,
93
93
  postProcessing?: {
94
94
  normalizeAudio: boolean
95
- targetPeakDb: number
96
- maxIncreaseDb: number
95
+ targetPeak: number
96
+ maxGainIncrease: number
97
97
 
98
- dryMixGainDb?: number
98
+ dryMixGain?: number
99
99
  }
100
100
  }
101
101
 
102
102
  export const defaultDenoisingOptions: DenoisingOptions = {
103
- method: "rnnoise",
103
+ method: 'rnnoise',
104
104
 
105
105
  postProcessing: {
106
106
  normalizeAudio: false,
107
- targetPeakDb: -3,
108
- maxIncreaseDb: 30,
109
- dryMixGainDb: -20,
107
+ targetPeak: -3,
108
+ maxGainIncrease: 30,
109
+ dryMixGain: -20,
110
110
  }
111
111
  }
112
112