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.
- package/README.md +15 -14
- package/data/schemas/options.json +398 -111
- package/dist/alignment/DTWMfccSequenceAlignment.d.ts +1 -1
- package/dist/alignment/DTWMfccSequenceAlignment.js +8 -8
- package/dist/alignment/DTWSequenceAlignment.d.ts +1 -1
- package/dist/alignment/DTWSequenceAlignment.js +1 -1
- package/dist/alignment/DTWSequenceAlignmentWindowed.d.ts +1 -1
- package/dist/alignment/DTWSequenceAlignmentWindowed.js +2 -2
- package/dist/alignment/LevenshteinSequenceAlignment.d.ts +1 -1
- package/dist/alignment/LevenshteinSequenceAlignment.js +1 -1
- package/dist/alignment/SpeechAlignment.d.ts +9 -10
- package/dist/alignment/SpeechAlignment.js +136 -105
- package/dist/alignment/SpeechAlignment.js.map +1 -1
- package/dist/api/API.d.ts +13 -12
- package/dist/api/API.js +14 -13
- package/dist/api/API.js.map +1 -1
- package/dist/api/APIOptions.d.ts +5 -4
- package/dist/api/Alignment.d.ts +15 -9
- package/dist/api/Alignment.js +88 -74
- package/dist/api/Alignment.js.map +1 -1
- package/dist/api/Common.js +1 -1
- package/dist/api/Denoising.d.ts +6 -6
- package/dist/api/Denoising.js +23 -23
- package/dist/api/Denoising.js.map +1 -1
- package/dist/api/LanguageDetection.d.ts +19 -12
- package/dist/api/LanguageDetection.js +88 -38
- package/dist/api/LanguageDetection.js.map +1 -1
- package/dist/api/Recognition.d.ts +16 -6
- package/dist/api/Recognition.js +129 -55
- package/dist/api/Recognition.js.map +1 -1
- package/dist/api/SourceSeparation.d.ts +17 -0
- package/dist/api/SourceSeparation.js +61 -0
- package/dist/api/SourceSeparation.js.map +1 -0
- package/dist/api/Synthesis.d.ts +18 -18
- package/dist/api/Synthesis.js +191 -164
- package/dist/api/Synthesis.js.map +1 -1
- package/dist/api/Translation.d.ts +19 -8
- package/dist/api/Translation.js +132 -35
- package/dist/api/Translation.js.map +1 -1
- package/dist/api/Vad.d.ts +10 -5
- package/dist/api/Vad.js +76 -38
- package/dist/api/Vad.js.map +1 -1
- package/dist/audio/AudioBufferConversion.d.ts +1 -1
- package/dist/audio/AudioBufferConversion.js +4 -4
- package/dist/audio/AudioPlayer.d.ts +1 -1
- package/dist/audio/AudioPlayer.js +26 -26
- package/dist/audio/AudioPlayer.js.map +1 -1
- package/dist/audio/AudioRecorder.d.ts +1 -1
- package/dist/audio/AudioRecorder.js +5 -5
- package/dist/audio/AudioUtilities.d.ts +13 -9
- package/dist/audio/AudioUtilities.js +86 -24
- package/dist/audio/AudioUtilities.js.map +1 -1
- package/dist/cli/CLI.d.ts +3 -3
- package/dist/cli/CLI.js +271 -162
- package/dist/cli/CLI.js.map +1 -1
- package/dist/cli/CLIConfigFile.js +8 -8
- package/dist/cli/CLILauncher.js +6 -6
- package/dist/cli/CLIOptionsSchema.js +2 -2
- package/dist/cli/CLIParser.js +5 -5
- package/dist/cli/CLIStarter.js +4 -4
- package/dist/codecs/FFMpegTranscoder.d.ts +2 -2
- package/dist/codecs/FFMpegTranscoder.js +37 -37
- package/dist/codecs/FFMpegTranscoder.js.map +1 -1
- package/dist/codecs/TIMITCodec.js +5 -5
- package/dist/codecs/WaveCodec.d.ts +1 -1
- package/dist/codecs/WaveCodec.js +22 -22
- package/dist/denoising/RNNoise.d.ts +1 -1
- package/dist/denoising/RNNoise.js +9 -9
- package/dist/dsp/BiquadFilter.d.ts +3 -2
- package/dist/dsp/BiquadFilter.js +18 -11
- package/dist/dsp/BiquadFilter.js.map +1 -1
- package/dist/dsp/DecayingPeakEstimator.d.ts +16 -0
- package/dist/dsp/DecayingPeakEstimator.js +23 -0
- package/dist/dsp/DecayingPeakEstimator.js.map +1 -0
- package/dist/dsp/FFT.d.ts +8 -4
- package/dist/dsp/FFT.js +76 -30
- package/dist/dsp/FFT.js.map +1 -1
- package/dist/dsp/KWeightingFilter.d.ts +9 -0
- package/dist/dsp/KWeightingFilter.js +40 -0
- package/dist/dsp/KWeightingFilter.js.map +1 -0
- package/dist/dsp/LoudnessEstimator.d.ts +21 -0
- package/dist/dsp/LoudnessEstimator.js +47 -0
- package/dist/dsp/LoudnessEstimator.js.map +1 -0
- package/dist/dsp/MFCC.d.ts +2 -2
- package/dist/dsp/MFCC.js +15 -15
- package/dist/dsp/MelSpectogram.d.ts +1 -1
- package/dist/dsp/MelSpectogram.js +6 -6
- package/dist/dsp/Rubberband.d.ts +11 -11
- package/dist/dsp/Rubberband.js +27 -27
- package/dist/dsp/Sonic.d.ts +1 -1
- package/dist/dsp/Sonic.js +3 -3
- package/dist/dsp/SpeexResampler.d.ts +1 -1
- package/dist/dsp/SpeexResampler.js +2 -2
- package/dist/math/VectorMath.d.ts +12 -8
- package/dist/math/VectorMath.js +35 -32
- package/dist/math/VectorMath.js.map +1 -1
- package/dist/nlp/ChineseSegmentation.js +2 -2
- package/dist/nlp/CompromiseNLP.js +3 -3
- package/dist/nlp/EspeakPhonemizer.js +30 -30
- package/dist/nlp/IPA.js +20 -20
- package/dist/nlp/JapaneseSegmentation.js +6 -6
- package/dist/nlp/Lexicon.d.ts +1 -1
- package/dist/nlp/Lexicon.js +7 -7
- package/dist/nlp/Segmentation.d.ts +3 -0
- package/dist/nlp/Segmentation.js +21 -14
- package/dist/nlp/Segmentation.js.map +1 -1
- package/dist/nlp/TextNormalizer.js +16 -16
- package/dist/recognition/AmazonTranscribeSTT.d.ts +2 -2
- package/dist/recognition/AmazonTranscribeSTT.js +13 -14
- package/dist/recognition/AmazonTranscribeSTT.js.map +1 -1
- package/dist/recognition/AzureCognitiveServicesSTT.js +5 -6
- package/dist/recognition/AzureCognitiveServicesSTT.js.map +1 -1
- package/dist/recognition/GoogleCloudSTT.d.ts +3 -3
- package/dist/recognition/GoogleCloudSTT.js +18 -18
- package/dist/recognition/OpenAICloudSTT.d.ts +19 -0
- package/dist/recognition/OpenAICloudSTT.js +81 -0
- package/dist/recognition/OpenAICloudSTT.js.map +1 -0
- package/dist/recognition/SileroSTT.d.ts +2 -2
- package/dist/recognition/SileroSTT.js +25 -25
- package/dist/recognition/VoskSTT.d.ts +2 -2
- package/dist/recognition/VoskSTT.js +8 -8
- package/dist/recognition/WhisperCppSTT.d.ts +88 -0
- package/dist/recognition/WhisperCppSTT.js +332 -0
- package/dist/recognition/WhisperCppSTT.js.map +1 -0
- package/dist/recognition/WhisperSTT.d.ts +49 -25
- package/dist/recognition/WhisperSTT.js +626 -481
- package/dist/recognition/WhisperSTT.js.map +1 -1
- package/dist/server/Client.d.ts +1 -1
- package/dist/server/Client.js +22 -22
- package/dist/server/Server.js +9 -9
- package/dist/server/Server.js.map +1 -1
- package/dist/server/Worker.d.ts +22 -22
- package/dist/server/Worker.js +36 -36
- package/dist/server/Worker.js.map +1 -1
- package/dist/server/WorkerStarter.js +2 -2
- package/dist/source-separation/MDXNetSourceSeparation.d.ts +11 -0
- package/dist/source-separation/MDXNetSourceSeparation.js +161 -0
- package/dist/source-separation/MDXNetSourceSeparation.js.map +1 -0
- package/dist/speech-language-detection/SileroLanguageDetection.d.ts +1 -1
- package/dist/speech-language-detection/SileroLanguageDetection.js +7 -7
- package/dist/subtitles/Subtitles.d.ts +10 -0
- package/dist/subtitles/Subtitles.js +2 -2
- package/dist/subtitles/Subtitles.js.map +1 -1
- package/dist/synthesis/AwsPollyTTS.d.ts +1 -1
- package/dist/synthesis/AwsPollyTTS.js +12 -12
- package/dist/synthesis/AzureCognitiveServicesTTS.js +7 -7
- package/dist/synthesis/CoquiServerTTS.js +10 -10
- package/dist/synthesis/CoquiServerTTS.js.map +1 -1
- package/dist/synthesis/ElevenlabsTTS.d.ts +23 -0
- package/dist/synthesis/ElevenlabsTTS.js +103 -0
- package/dist/synthesis/ElevenlabsTTS.js.map +1 -0
- package/dist/synthesis/EspeakTTS.d.ts +6 -5
- package/dist/synthesis/EspeakTTS.js +81 -69
- package/dist/synthesis/EspeakTTS.js.map +1 -1
- package/dist/synthesis/FliteTTS.d.ts +3 -3
- package/dist/synthesis/FliteTTS.js +154 -154
- package/dist/synthesis/FliteTTS.js.map +1 -1
- package/dist/synthesis/GoogleCloudTTS.d.ts +3 -3
- package/dist/synthesis/GoogleCloudTTS.js +17 -17
- package/dist/synthesis/GoogleCloudTTS.js.map +1 -1
- package/dist/synthesis/GoogleTranslateTTS.d.ts +1 -1
- package/dist/synthesis/GoogleTranslateTTS.js +103 -103
- package/dist/synthesis/MicrosoftEdgeTTS.d.ts +2 -2
- package/dist/synthesis/MicrosoftEdgeTTS.js +74 -74
- package/dist/synthesis/OpenAICloudTTS.d.ts +13 -0
- package/dist/synthesis/OpenAICloudTTS.js +169 -0
- package/dist/synthesis/OpenAICloudTTS.js.map +1 -0
- package/dist/synthesis/SamTTS.js +3 -3
- package/dist/synthesis/SapiTTS.d.ts +3 -3
- package/dist/synthesis/SapiTTS.js +26 -26
- package/dist/synthesis/StreamlabsPollyTTS.d.ts +2 -2
- package/dist/synthesis/StreamlabsPollyTTS.js +27 -27
- package/dist/synthesis/SvoxPicoTTS.d.ts +2 -2
- package/dist/synthesis/SvoxPicoTTS.js +65 -65
- package/dist/synthesis/SvoxPicoTTS.js.map +1 -1
- package/dist/synthesis/VitsTTS.d.ts +3 -3
- package/dist/synthesis/VitsTTS.js +378 -378
- package/dist/synthesis/VitsTTS.js.map +1 -1
- package/dist/tests/Test.js +2 -2
- package/dist/utilities/Compression.d.ts +5 -0
- package/dist/utilities/Compression.js +29 -13
- package/dist/utilities/Compression.js.map +1 -1
- package/dist/utilities/FileDownloader.d.ts +1 -1
- package/dist/utilities/FileDownloader.js +16 -16
- package/dist/utilities/FileSystem.js +7 -7
- package/dist/utilities/Locale.d.ts +7 -7
- package/dist/utilities/Locale.js +15 -15
- package/dist/utilities/Logger.js +3 -3
- package/dist/utilities/ObjectUtilities.js +19 -19
- package/dist/utilities/OpenPromise.js +2 -2
- package/dist/utilities/OpenPromise.js.map +1 -1
- package/dist/utilities/PackageManager.js +31 -0
- package/dist/utilities/PackageManager.js.map +1 -1
- package/dist/utilities/PathUtilities.js +8 -8
- package/dist/utilities/RandomGenerator.js +2 -2
- package/dist/utilities/SmoothEstimator.d.ts +8 -0
- package/dist/utilities/SmoothEstimator.js +25 -0
- package/dist/utilities/SmoothEstimator.js.map +1 -0
- package/dist/utilities/TarballMaker.js +8 -8
- package/dist/utilities/Timeline.d.ts +3 -2
- package/dist/utilities/Timeline.js +11 -11
- package/dist/utilities/Timeline.js.map +1 -1
- package/dist/utilities/Timer.js +4 -4
- package/dist/utilities/Utilities.d.ts +4 -0
- package/dist/utilities/Utilities.js +38 -15
- package/dist/utilities/Utilities.js.map +1 -1
- package/dist/utilities/WasmMemoryManager.js +7 -7
- package/dist/utilities/WebReader.js +23 -23
- package/dist/utilities/WikipediaReader.js +2 -2
- package/dist/voice-activity-detection/AdaptiveGateVAD.d.ts +28 -0
- package/dist/voice-activity-detection/AdaptiveGateVAD.js +138 -0
- package/dist/voice-activity-detection/AdaptiveGateVAD.js.map +1 -0
- package/dist/voice-activity-detection/SileroVAD.d.ts +1 -1
- package/dist/voice-activity-detection/SileroVAD.js +5 -5
- package/dist/voice-activity-detection/SileroVAD.js.map +1 -1
- package/dist/voice-activity-detection/WebRtcVAD.d.ts +1 -1
- package/dist/voice-activity-detection/WebRtcVAD.js +4 -4
- package/docs/API.md +29 -11
- package/docs/CLI.md +31 -7
- package/docs/Contributing.md +38 -0
- package/docs/Development.md +93 -19
- package/docs/Engines.md +28 -16
- package/docs/Licenses.md +4 -1
- package/docs/Options.md +158 -78
- package/docs/Releases.md +262 -0
- package/docs/Server.md +7 -7
- package/docs/Tasklist.md +95 -76
- package/docs/Technical.md +4 -4
- package/package.json +13 -14
- package/src/alignment/DTWMfccSequenceAlignment.ts +9 -9
- package/src/alignment/DTWSequenceAlignment.ts +2 -2
- package/src/alignment/DTWSequenceAlignmentWindowed.ts +3 -3
- package/src/alignment/LevenshteinSequenceAlignment.ts +2 -2
- package/src/alignment/SpeechAlignment.ts +204 -119
- package/src/api/API.ts +14 -13
- package/src/api/APIOptions.ts +12 -11
- package/src/api/Alignment.ts +147 -90
- package/src/api/Common.ts +1 -1
- package/src/api/Denoising.ts +28 -28
- package/src/api/LanguageDetection.ts +135 -48
- package/src/api/Recognition.ts +198 -59
- package/src/api/SourceSeparation.ts +99 -0
- package/src/api/Synthesis.ts +217 -181
- package/src/api/Translation.ts +193 -40
- package/src/api/Vad.ts +110 -41
- package/src/audio/AudioBufferConversion.ts +4 -4
- package/src/audio/AudioPlayer.ts +27 -27
- package/src/audio/AudioRecorder.ts +5 -5
- package/src/audio/AudioUtilities.ts +107 -24
- package/src/cli/CLI.ts +313 -164
- package/src/cli/CLIConfigFile.ts +8 -8
- package/src/cli/CLILauncher.ts +6 -6
- package/src/cli/CLIOptionsSchema.ts +2 -2
- package/src/cli/CLIParser.ts +5 -5
- package/src/cli/CLIStarter.ts +4 -4
- package/src/codecs/FFMpegTranscoder.ts +38 -38
- package/src/codecs/TIMITCodec.ts +5 -5
- package/src/codecs/WaveCodec.ts +22 -22
- package/src/denoising/RNNoise.ts +9 -9
- package/src/dsp/BiquadFilter.ts +19 -11
- package/src/dsp/DecayingPeakEstimator.ts +35 -0
- package/src/dsp/FFT.ts +103 -35
- package/src/dsp/KWeightingFilter.ts +43 -0
- package/src/dsp/LoudnessEstimator.ts +74 -0
- package/src/dsp/MFCC.ts +15 -15
- package/src/dsp/MelSpectogram.ts +7 -7
- package/src/dsp/Rubberband.ts +38 -38
- package/src/dsp/Sonic.ts +4 -4
- package/src/dsp/SpeexResampler.ts +2 -2
- package/src/math/VectorMath.ts +42 -33
- package/src/nlp/ChineseSegmentation.ts +3 -3
- package/src/nlp/CompromiseNLP.ts +3 -3
- package/src/nlp/EspeakPhonemizer.ts +30 -30
- package/src/nlp/IPA.ts +20 -20
- package/src/nlp/JapaneseSegmentation.ts +6 -6
- package/src/nlp/Lexicon.ts +8 -8
- package/src/nlp/Segmentation.ts +23 -14
- package/src/nlp/TextNormalizer.ts +16 -16
- package/src/recognition/AmazonTranscribeSTT.ts +16 -17
- package/src/recognition/AzureCognitiveServicesSTT.ts +8 -6
- package/src/recognition/GoogleCloudSTT.ts +21 -21
- package/src/recognition/OpenAICloudSTT.ts +142 -0
- package/src/recognition/SileroSTT.ts +26 -26
- package/src/recognition/VoskSTT.ts +10 -10
- package/src/recognition/WhisperCppSTT.ts +555 -0
- package/src/recognition/WhisperSTT.ts +760 -507
- package/src/server/Client.ts +23 -23
- package/src/server/Server.ts +9 -9
- package/src/server/Worker.ts +53 -53
- package/src/server/WorkerStarter.ts +2 -2
- package/src/source-separation/MDXNetSourceSeparation.ts +228 -0
- package/src/speech-language-detection/SileroLanguageDetection.ts +8 -8
- package/src/subtitles/Subtitles.ts +3 -3
- package/src/synthesis/AwsPollyTTS.ts +14 -14
- package/src/synthesis/AzureCognitiveServicesTTS.ts +10 -10
- package/src/synthesis/CoquiServerTTS.ts +10 -10
- package/src/synthesis/ElevenlabsTTS.ts +137 -0
- package/src/synthesis/EspeakTTS.ts +90 -71
- package/src/synthesis/FliteTTS.ts +157 -157
- package/src/synthesis/GoogleCloudTTS.ts +19 -19
- package/src/synthesis/GoogleTranslateTTS.ts +104 -104
- package/src/synthesis/MicrosoftEdgeTTS.ts +80 -80
- package/src/synthesis/OpenAICloudTTS.ts +196 -0
- package/src/synthesis/SamTTS.ts +3 -3
- package/src/synthesis/SapiTTS.ts +29 -29
- package/src/synthesis/StreamlabsPollyTTS.ts +29 -29
- package/src/synthesis/SvoxPicoTTS.ts +67 -67
- package/src/synthesis/VitsTTS.ts +380 -380
- package/src/tests/Test.ts +4 -4
- package/src/utilities/Compression.ts +34 -13
- package/src/utilities/FileDownloader.ts +19 -19
- package/src/utilities/FileSystem.ts +7 -7
- package/src/utilities/Locale.ts +22 -22
- package/src/utilities/Logger.ts +4 -4
- package/src/utilities/ObjectUtilities.ts +19 -19
- package/src/utilities/OpenPromise.ts +2 -2
- package/src/utilities/PackageManager.ts +40 -0
- package/src/utilities/PathUtilities.ts +8 -8
- package/src/utilities/RandomGenerator.ts +3 -3
- package/src/utilities/SmoothEstimator.ts +35 -0
- package/src/utilities/TarballMaker.ts +9 -9
- package/src/utilities/Timeline.ts +15 -13
- package/src/utilities/Timer.ts +4 -4
- package/src/utilities/Utilities.ts +49 -15
- package/src/utilities/WasmMemoryManager.ts +7 -7
- package/src/utilities/WebReader.ts +23 -23
- package/src/utilities/WikipediaReader.ts +2 -2
- package/src/voice-activity-detection/AdaptiveGateVAD.ts +202 -0
- package/src/voice-activity-detection/SileroVAD.ts +5 -5
- package/src/voice-activity-detection/WebRtcVAD.ts +5 -5
- package/dist/synthesis/ElevenLabsTTS.d.ts +0 -8
- package/dist/synthesis/ElevenLabsTTS.js +0 -82
- package/dist/synthesis/ElevenLabsTTS.js.map +0 -1
- package/src/synthesis/ElevenLabsTTS.ts +0 -104
package/src/api/Alignment.ts
CHANGED
|
@@ -1,36 +1,61 @@
|
|
|
1
|
-
import { extendDeep } from
|
|
2
|
-
|
|
3
|
-
import { logToStderr } from
|
|
4
|
-
import { AudioSourceParam, RawAudio,
|
|
5
|
-
import { Logger } from
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import {
|
|
14
|
-
|
|
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
|
-
|
|
23
|
+
options = extendDeep(defaultAlignmentOptions, options)
|
|
25
24
|
|
|
26
25
|
const inputRawAudio = await ensureRawAudio(input)
|
|
27
26
|
|
|
28
|
-
let sourceRawAudio
|
|
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(
|
|
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(
|
|
62
|
-
|
|
63
|
-
const { alignUsingDtwWithRecognition, alignUsingDtw } = await import("../alignment/SpeechAlignment.js")
|
|
86
|
+
logger.start('Load alignment module')
|
|
64
87
|
|
|
65
|
-
|
|
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
|
|
127
|
-
const {
|
|
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
|
|
138
|
-
|
|
139
|
-
|
|
141
|
+
case 'dtw-ra': {
|
|
142
|
+
const recognitionOptions: API.RecognitionOptions =
|
|
143
|
+
extendDeep({ crop: options.crop, language }, options.recognition)
|
|
140
144
|
|
|
141
|
-
|
|
142
|
-
//promptWords.reverse()
|
|
145
|
+
logger.end()
|
|
143
146
|
|
|
144
|
-
|
|
145
|
-
|
|
147
|
+
// Recognize source audio
|
|
148
|
+
const { transcript: recognizedTranscript, wordTimeline: recognitionTimeline } = await API.recognize(sourceRawAudio, recognitionOptions)
|
|
146
149
|
|
|
147
|
-
|
|
148
|
-
|
|
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
|
|
153
|
+
const {
|
|
154
|
+
referenceRawAudio,
|
|
155
|
+
referenceTimeline,
|
|
156
|
+
} = await createAlignmentReferenceUsingEspeak(transcript, language, options.plainText, options.customLexiconPaths, true)
|
|
153
157
|
|
|
154
|
-
|
|
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 {
|
|
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
|
-
|
|
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
|
|
174
|
-
const WhisperSTT = await import(
|
|
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
|
|
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(
|
|
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,
|
|
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
|
-
|
|
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 =
|
|
255
|
-
export type PhoneAlignmentMethod =
|
|
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
|
-
|
|
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:
|
|
317
|
+
engine: 'dtw',
|
|
283
318
|
|
|
284
319
|
language: undefined,
|
|
285
320
|
|
|
286
|
-
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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
package/src/api/Denoising.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { extendDeep } from
|
|
1
|
+
import { extendDeep } from '../utilities/ObjectUtilities.js'
|
|
2
2
|
|
|
3
|
-
import { AudioSourceParam, RawAudio, applyGainDecibels, ensureRawAudio,
|
|
4
|
-
import { Logger } from
|
|
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
|
|
7
|
-
import { resampleAudioSpeex } from
|
|
8
|
-
import { EngineMetadata } from
|
|
9
|
-
import chalk from
|
|
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(
|
|
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
|
|
34
|
-
const RNNoise = await import(
|
|
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(
|
|
56
|
+
logger.start('Postprocess audio')
|
|
57
57
|
|
|
58
58
|
const shouldNormalize = options.postProcessing!.normalizeAudio!
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
const
|
|
59
|
+
const targetPeakDecibels = options.postProcessing!.targetPeak!
|
|
60
|
+
const maxGainIncreaseDecibels = options.postProcessing!.maxGainIncrease!
|
|
61
|
+
const dryMixGainDecibels = options.postProcessing!.dryMixGain!
|
|
62
62
|
|
|
63
|
-
const
|
|
64
|
-
denoisedAudio = mixAudio(denoisedAudio, applyGainDecibels(resampledRawAudio,
|
|
65
|
-
const
|
|
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,
|
|
68
|
+
denoisedAudio = normalizeAudioLevel(denoisedAudio, targetPeakDecibels, maxGainIncreaseDecibels)
|
|
69
69
|
} else {
|
|
70
|
-
denoisedAudio = applyGainDecibels(denoisedAudio,
|
|
70
|
+
denoisedAudio = applyGainDecibels(denoisedAudio, preMixPeakDecibels - postMixPeakDecibels)
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
logger.end()
|
|
74
74
|
|
|
75
75
|
logger.log('')
|
|
76
|
-
logger.logDuration(
|
|
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 =
|
|
89
|
+
export type DenoisingMethod = 'rnnoise'
|
|
90
90
|
|
|
91
91
|
export interface DenoisingOptions {
|
|
92
92
|
method?: DenoisingMethod,
|
|
93
93
|
postProcessing?: {
|
|
94
94
|
normalizeAudio: boolean
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
targetPeak: number
|
|
96
|
+
maxGainIncrease: number
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
dryMixGain?: number
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
export const defaultDenoisingOptions: DenoisingOptions = {
|
|
103
|
-
method:
|
|
103
|
+
method: 'rnnoise',
|
|
104
104
|
|
|
105
105
|
postProcessing: {
|
|
106
106
|
normalizeAudio: false,
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
targetPeak: -3,
|
|
108
|
+
maxGainIncrease: 30,
|
|
109
|
+
dryMixGain: -20,
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
|