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
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { deepClone, extendDeep } from
|
|
2
|
-
import { ensureRawAudio, getRawAudioDuration, normalizeAudioLevel, sliceRawAudioByTime, trimAudioEnd } from
|
|
3
|
-
import { Logger } from
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
1
|
+
import { deepClone, extendDeep } from '../utilities/ObjectUtilities.js';
|
|
2
|
+
import { ensureRawAudio, getRawAudioDuration, normalizeAudioLevel, sliceRawAudioByTime, trimAudioEnd } from '../audio/AudioUtilities.js';
|
|
3
|
+
import { Logger } from '../utilities/Logger.js';
|
|
4
|
+
import * as API from './API.js';
|
|
5
|
+
import { logToStderr } from '../utilities/Utilities.js';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import { formatLanguageCodeWithName, languageCodeToName } from '../utilities/Locale.js';
|
|
8
|
+
import { loadPackage } from '../utilities/PackageManager.js';
|
|
9
|
+
import chalk from 'chalk';
|
|
9
10
|
const log = logToStderr;
|
|
10
11
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
11
12
|
// Speech language detection
|
|
@@ -13,35 +14,49 @@ const log = logToStderr;
|
|
|
13
14
|
export async function detectSpeechLanguage(input, options) {
|
|
14
15
|
const logger = new Logger();
|
|
15
16
|
const startTime = logger.getTimestamp();
|
|
16
|
-
|
|
17
|
+
options = extendDeep(defaultSpeechLanguageDetectionOptions, options);
|
|
17
18
|
const inputRawAudio = await ensureRawAudio(input);
|
|
18
19
|
let sourceRawAudio = await ensureRawAudio(inputRawAudio, 16000, 1);
|
|
19
20
|
sourceRawAudio = normalizeAudioLevel(sourceRawAudio);
|
|
20
21
|
sourceRawAudio.audioChannels[0] = trimAudioEnd(sourceRawAudio.audioChannels[0]);
|
|
21
|
-
|
|
22
|
+
if (options.crop) {
|
|
23
|
+
logger.start('Crop using voice activity detection');
|
|
24
|
+
({ croppedRawAudio: sourceRawAudio } = await API.detectVoiceActivity(sourceRawAudio, options.vad));
|
|
25
|
+
logger.end();
|
|
26
|
+
}
|
|
27
|
+
logger.start('Prepare for speech language detection');
|
|
22
28
|
const defaultLanguage = options.defaultLanguage;
|
|
23
29
|
const fallbackThresholdProbability = options.fallbackThresholdProbability;
|
|
24
30
|
logger.start(`Initialize ${options.engine} module`);
|
|
25
31
|
let detectedLanguageProbabilities;
|
|
26
32
|
switch (options.engine) {
|
|
27
|
-
case
|
|
28
|
-
const SileroLanguageDetection = await import(
|
|
33
|
+
case 'silero': {
|
|
34
|
+
const SileroLanguageDetection = await import('../speech-language-detection/SileroLanguageDetection.js');
|
|
29
35
|
logger.end();
|
|
30
36
|
const sileroOptions = options.silero;
|
|
31
|
-
const modelDir = await loadPackage(
|
|
32
|
-
const modelPath = path.join(modelDir,
|
|
33
|
-
const languageDictionaryPath = path.join(modelDir,
|
|
34
|
-
const languageGroupDictionaryPath = path.join(modelDir,
|
|
37
|
+
const modelDir = await loadPackage('silero-lang-classifier-95');
|
|
38
|
+
const modelPath = path.join(modelDir, 'lang_classifier_95.onnx');
|
|
39
|
+
const languageDictionaryPath = path.join(modelDir, 'lang_dict_95.json');
|
|
40
|
+
const languageGroupDictionaryPath = path.join(modelDir, 'lang_group_dict_95.json');
|
|
35
41
|
const languageResults = await SileroLanguageDetection.detectLanguage(sourceRawAudio, modelPath, languageDictionaryPath, languageGroupDictionaryPath);
|
|
36
42
|
detectedLanguageProbabilities = languageResults;
|
|
37
43
|
break;
|
|
38
44
|
}
|
|
39
|
-
case
|
|
40
|
-
const WhisperSTT = await import(
|
|
45
|
+
case 'whisper': {
|
|
46
|
+
const WhisperSTT = await import('../recognition/WhisperSTT.js');
|
|
41
47
|
const whisperOptions = options.whisper;
|
|
42
|
-
const { modelName, modelDir
|
|
48
|
+
const { modelName, modelDir } = await WhisperSTT.loadPackagesAndGetPaths(whisperOptions.model, undefined);
|
|
49
|
+
logger.end();
|
|
50
|
+
detectedLanguageProbabilities = await WhisperSTT.detectLanguage(sourceRawAudio, modelName, modelDir, whisperOptions.temperature);
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
case 'whisper.cpp': {
|
|
54
|
+
const WhisperCppSTT = await import('../recognition/WhisperCppSTT.js');
|
|
55
|
+
const whisperCppOptions = options.whisperCpp;
|
|
43
56
|
logger.end();
|
|
44
|
-
|
|
57
|
+
const { modelName, modelPath } = await WhisperCppSTT.loadModelPackage(whisperCppOptions.model, undefined);
|
|
58
|
+
logger.end();
|
|
59
|
+
detectedLanguageProbabilities = await WhisperCppSTT.detectLanguage(sourceRawAudio, modelName, modelPath);
|
|
45
60
|
break;
|
|
46
61
|
}
|
|
47
62
|
default: {
|
|
@@ -57,12 +72,20 @@ export async function detectSpeechLanguage(input, options) {
|
|
|
57
72
|
detectedLanguage = detectedLanguageProbabilities[0].language;
|
|
58
73
|
}
|
|
59
74
|
logger.end();
|
|
60
|
-
logger.logDuration(
|
|
61
|
-
return {
|
|
75
|
+
logger.logDuration('\nTotal detection time', startTime, chalk.magentaBright);
|
|
76
|
+
return {
|
|
77
|
+
detectedLanguage,
|
|
78
|
+
detectedLanguageName: languageCodeToName(detectedLanguage),
|
|
79
|
+
detectedLanguageProbabilities,
|
|
80
|
+
inputRawAudio,
|
|
81
|
+
};
|
|
62
82
|
}
|
|
63
|
-
export async function detectSpeechLanguageByParts(sourceRawAudio, getResultsForAudioPart, audioPartDuration = 30, hopDuration =
|
|
83
|
+
export async function detectSpeechLanguageByParts(sourceRawAudio, getResultsForAudioPart, audioPartDuration = 30, hopDuration = 25) {
|
|
64
84
|
const logger = new Logger();
|
|
65
85
|
const audioDuration = getRawAudioDuration(sourceRawAudio);
|
|
86
|
+
if (audioDuration === 0) {
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
66
89
|
const resultsForParts = [];
|
|
67
90
|
for (let audioTimeOffset = 0; audioTimeOffset < audioDuration; audioTimeOffset += hopDuration) {
|
|
68
91
|
const startOffset = audioTimeOffset;
|
|
@@ -73,7 +96,11 @@ export async function detectSpeechLanguageByParts(sourceRawAudio, getResultsForA
|
|
|
73
96
|
const resultsForPart = await getResultsForAudioPart(audioPart);
|
|
74
97
|
resultsForParts.push(resultsForPart);
|
|
75
98
|
const sortedResultsForPart = deepClone(resultsForPart).sort((a, b) => b.probability - a.probability);
|
|
76
|
-
|
|
99
|
+
let topCandidatesStrings = [];
|
|
100
|
+
for (let i = 0; i < Math.min(3, sortedResultsForPart.length); i++) {
|
|
101
|
+
topCandidatesStrings.push(`${formatLanguageCodeWithName(sortedResultsForPart[i].language)}: ${sortedResultsForPart[i].probability.toFixed(3)}`);
|
|
102
|
+
}
|
|
103
|
+
logger.logTitledMessage(`Top candidates`, topCandidatesStrings.join(', '));
|
|
77
104
|
if (audioPartLength < audioPartDuration) {
|
|
78
105
|
break;
|
|
79
106
|
}
|
|
@@ -91,10 +118,20 @@ export async function detectSpeechLanguageByParts(sourceRawAudio, getResultsForA
|
|
|
91
118
|
return averagedResults;
|
|
92
119
|
}
|
|
93
120
|
export const defaultSpeechLanguageDetectionOptions = {
|
|
94
|
-
engine:
|
|
121
|
+
engine: 'whisper',
|
|
122
|
+
defaultLanguage: 'en',
|
|
123
|
+
fallbackThresholdProbability: 0.05,
|
|
124
|
+
crop: true,
|
|
95
125
|
silero: {},
|
|
96
126
|
whisper: {
|
|
97
|
-
model:
|
|
127
|
+
model: 'tiny',
|
|
128
|
+
temperature: 1.0
|
|
129
|
+
},
|
|
130
|
+
whisperCpp: {
|
|
131
|
+
model: 'tiny'
|
|
132
|
+
},
|
|
133
|
+
vad: {
|
|
134
|
+
engine: 'adaptive-gate'
|
|
98
135
|
}
|
|
99
136
|
};
|
|
100
137
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
@@ -108,15 +145,15 @@ export async function detectTextLanguage(input, options) {
|
|
|
108
145
|
let detectedLanguageProbabilities;
|
|
109
146
|
logger.start(`Initialize ${options.engine} module`);
|
|
110
147
|
switch (options.engine) {
|
|
111
|
-
case
|
|
112
|
-
const { detectLanguage } = await import(
|
|
113
|
-
logger.start(
|
|
148
|
+
case 'tinyld': {
|
|
149
|
+
const { detectLanguage } = await import('../text-language-detection/TinyLDLanguageDetection.js');
|
|
150
|
+
logger.start('Detecting text language using tinyld');
|
|
114
151
|
detectedLanguageProbabilities = await detectLanguage(input);
|
|
115
152
|
break;
|
|
116
153
|
}
|
|
117
|
-
case
|
|
118
|
-
const { detectLanguage } = await import(
|
|
119
|
-
logger.start(
|
|
154
|
+
case 'fasttext': {
|
|
155
|
+
const { detectLanguage } = await import('../text-language-detection/FastTextLanguageDetection.js');
|
|
156
|
+
logger.start('Detecting text language using FastText');
|
|
120
157
|
detectedLanguageProbabilities = await detectLanguage(input);
|
|
121
158
|
break;
|
|
122
159
|
}
|
|
@@ -133,12 +170,19 @@ export async function detectTextLanguage(input, options) {
|
|
|
133
170
|
detectedLanguage = detectedLanguageProbabilities[0].language;
|
|
134
171
|
}
|
|
135
172
|
logger.end();
|
|
136
|
-
return {
|
|
173
|
+
return {
|
|
174
|
+
detectedLanguage,
|
|
175
|
+
detectedLanguageName: languageCodeToName(detectedLanguage),
|
|
176
|
+
detectedLanguageProbabilities
|
|
177
|
+
};
|
|
137
178
|
}
|
|
179
|
+
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
180
|
+
// Constants
|
|
181
|
+
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
138
182
|
export const defaultTextLanguageDetectionOptions = {
|
|
139
|
-
engine:
|
|
140
|
-
defaultLanguage:
|
|
141
|
-
fallbackThresholdProbability: 0.05
|
|
183
|
+
engine: 'tinyld',
|
|
184
|
+
defaultLanguage: 'en',
|
|
185
|
+
fallbackThresholdProbability: 0.05,
|
|
142
186
|
};
|
|
143
187
|
export const speechLanguageDetectionEngines = [
|
|
144
188
|
{
|
|
@@ -150,7 +194,13 @@ export const speechLanguageDetectionEngines = [
|
|
|
150
194
|
{
|
|
151
195
|
id: 'whisper',
|
|
152
196
|
name: 'OpenAI Whisper',
|
|
153
|
-
description: 'Uses the language
|
|
197
|
+
description: 'Uses the language tokens produced by the Whisper model to classify the spoken langauge.',
|
|
198
|
+
type: 'local'
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
id: 'whisper.cpp',
|
|
202
|
+
name: 'OpenAI Whisper (C++ port)',
|
|
203
|
+
description: 'Uses the language tokens produced by Whisper.cpp to classify the spoken langauge.',
|
|
154
204
|
type: 'local'
|
|
155
205
|
},
|
|
156
206
|
];
|
|
@@ -164,7 +214,7 @@ export const textLanguageDetectionEngines = [
|
|
|
164
214
|
{
|
|
165
215
|
id: 'fasttext',
|
|
166
216
|
name: 'FastText',
|
|
167
|
-
description: '
|
|
217
|
+
description: 'A library for word representations and sentence classification by Facebook research.',
|
|
168
218
|
type: 'local'
|
|
169
219
|
},
|
|
170
220
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LanguageDetection.js","sourceRoot":"","sources":["../../src/api/LanguageDetection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAEvE,OAAO,EAA8B,cAAc,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AACpK,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"LanguageDetection.js","sourceRoot":"","sources":["../../src/api/LanguageDetection.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { AudioSourceParam, RawAudio } from
|
|
2
|
-
import * as API from
|
|
3
|
-
import { Timeline } from
|
|
4
|
-
import { type WhisperOptions } from
|
|
5
|
-
import { SubtitlesConfig } from
|
|
1
|
+
import { AudioSourceParam, RawAudio } from '../audio/AudioUtilities.js';
|
|
2
|
+
import * as API from './API.js';
|
|
3
|
+
import { Timeline } from '../utilities/Timeline.js';
|
|
4
|
+
import { type WhisperOptions } from '../recognition/WhisperSTT.js';
|
|
5
|
+
import { SubtitlesConfig } from '../subtitles/Subtitles.js';
|
|
6
|
+
import { OpenAICloudSTTOptions } from '../recognition/OpenAICloudSTT.js';
|
|
7
|
+
import { WhisperCppOptions } from '../recognition/WhisperCppSTT.js';
|
|
6
8
|
export declare function recognize(input: AudioSourceParam, options: RecognitionOptions): Promise<RecognitionResult>;
|
|
7
9
|
export interface RecognitionResult {
|
|
8
10
|
transcript: string;
|
|
@@ -10,16 +12,23 @@ export interface RecognitionResult {
|
|
|
10
12
|
wordTimeline: Timeline;
|
|
11
13
|
language: string;
|
|
12
14
|
inputRawAudio: RawAudio;
|
|
15
|
+
isolatedRawAudio?: RawAudio;
|
|
16
|
+
backgroundRawAudio?: RawAudio;
|
|
13
17
|
}
|
|
14
|
-
export type RecognitionEngine =
|
|
18
|
+
export type RecognitionEngine = 'whisper' | 'whisper.cpp' | 'vosk' | 'silero' | 'google-cloud' | 'microsoft-azure' | 'amazon-transcribe' | 'openai-cloud';
|
|
15
19
|
export interface RecognitionOptions {
|
|
16
20
|
engine?: RecognitionEngine;
|
|
17
21
|
language?: string;
|
|
18
22
|
maxAlternatives?: number;
|
|
23
|
+
isolate?: boolean;
|
|
24
|
+
crop?: boolean;
|
|
19
25
|
alignment?: API.AlignmentOptions;
|
|
20
26
|
languageDetection?: API.SpeechLanguageDetectionOptions;
|
|
21
27
|
subtitles?: SubtitlesConfig;
|
|
28
|
+
vad?: API.VADOptions;
|
|
29
|
+
sourceSeparation?: API.SourceSeparationOptions;
|
|
22
30
|
whisper?: WhisperOptions;
|
|
31
|
+
whisperCpp?: WhisperCppOptions;
|
|
23
32
|
vosk?: {
|
|
24
33
|
modelPath?: string;
|
|
25
34
|
};
|
|
@@ -42,6 +51,7 @@ export interface RecognitionOptions {
|
|
|
42
51
|
accessKeyId?: string;
|
|
43
52
|
secretAccessKey?: string;
|
|
44
53
|
};
|
|
54
|
+
openAICloud?: OpenAICloudSTTOptions;
|
|
45
55
|
}
|
|
46
56
|
export declare const defaultRecognitionOptions: RecognitionOptions;
|
|
47
57
|
export declare const recognitionEngines: API.EngineMetadata[];
|
package/dist/api/Recognition.js
CHANGED
|
@@ -1,51 +1,82 @@
|
|
|
1
|
-
import { extendDeep } from
|
|
2
|
-
import { logToStderr } from
|
|
3
|
-
import { ensureRawAudio, normalizeAudioLevel, trimAudioEnd } from
|
|
4
|
-
import { Logger } from
|
|
5
|
-
import * as API from
|
|
6
|
-
import { addWordTextOffsetsToTimeline, wordTimelineToSegmentSentenceTimeline } from
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
1
|
+
import { extendDeep } from '../utilities/ObjectUtilities.js';
|
|
2
|
+
import { logToStderr } from '../utilities/Utilities.js';
|
|
3
|
+
import { ensureRawAudio, normalizeAudioLevel, trimAudioEnd } from '../audio/AudioUtilities.js';
|
|
4
|
+
import { Logger } from '../utilities/Logger.js';
|
|
5
|
+
import * as API from './API.js';
|
|
6
|
+
import { addWordTextOffsetsToTimeline, wordTimelineToSegmentSentenceTimeline } from '../utilities/Timeline.js';
|
|
7
|
+
import { formatLanguageCodeWithName, getShortLanguageCode, normalizeLanguageCode } from '../utilities/Locale.js';
|
|
8
|
+
import { loadPackage } from '../utilities/PackageManager.js';
|
|
9
|
+
import chalk from 'chalk';
|
|
10
|
+
import { defaultSubtitlesBaseConfig } from '../subtitles/Subtitles.js';
|
|
11
|
+
import { defaultOpenAICloudSTTOptions } from '../recognition/OpenAICloudSTT.js';
|
|
12
12
|
const log = logToStderr;
|
|
13
13
|
export async function recognize(input, options) {
|
|
14
14
|
const logger = new Logger();
|
|
15
15
|
const startTimestamp = logger.getTimestamp();
|
|
16
|
-
|
|
16
|
+
options = extendDeep(defaultRecognitionOptions, options);
|
|
17
17
|
const inputRawAudio = await ensureRawAudio(input);
|
|
18
|
-
let sourceRawAudio
|
|
18
|
+
let sourceRawAudio;
|
|
19
|
+
let isolatedRawAudio;
|
|
20
|
+
let backgroundRawAudio;
|
|
21
|
+
if (options.isolate) {
|
|
22
|
+
logger.log(``);
|
|
23
|
+
logger.end();
|
|
24
|
+
({ isolatedRawAudio, backgroundRawAudio } = await API.isolate(inputRawAudio, options.sourceSeparation));
|
|
25
|
+
logger.end();
|
|
26
|
+
logger.log(``);
|
|
27
|
+
sourceRawAudio = await ensureRawAudio(isolatedRawAudio, 16000, 1);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
sourceRawAudio = await ensureRawAudio(inputRawAudio, 16000, 1);
|
|
31
|
+
}
|
|
32
|
+
let sourceUncropTimeline;
|
|
33
|
+
if (options.crop) {
|
|
34
|
+
logger.start('Crop using voice activity detection');
|
|
35
|
+
({ timeline: sourceUncropTimeline, croppedRawAudio: sourceRawAudio } = await API.detectVoiceActivity(sourceRawAudio, options.vad));
|
|
36
|
+
logger.end();
|
|
37
|
+
}
|
|
38
|
+
logger.start('Prepare for recognition');
|
|
19
39
|
sourceRawAudio = normalizeAudioLevel(sourceRawAudio);
|
|
20
40
|
sourceRawAudio.audioChannels[0] = trimAudioEnd(sourceRawAudio.audioChannels[0]);
|
|
21
|
-
options = extendDeep(defaultRecognitionOptions, options);
|
|
22
41
|
const engine = options.engine;
|
|
23
|
-
if (!options.language) { // && options.engine !=
|
|
24
|
-
logger.start(
|
|
25
|
-
const { detectedLanguage } = await API.detectSpeechLanguage(
|
|
42
|
+
if (!options.language) { // && options.engine != 'whisper') {
|
|
43
|
+
logger.start('No language specified. Detecting speech language');
|
|
44
|
+
const { detectedLanguage } = await API.detectSpeechLanguage(sourceRawAudio, options.languageDetection);
|
|
26
45
|
logger.end();
|
|
27
46
|
logger.logTitledMessage('Language detected', formatLanguageCodeWithName(detectedLanguage));
|
|
28
47
|
options.language = detectedLanguage;
|
|
29
48
|
}
|
|
30
|
-
|
|
49
|
+
else {
|
|
50
|
+
logger.end();
|
|
51
|
+
const specifiedLanguageFormatted = formatLanguageCodeWithName(getShortLanguageCode(normalizeLanguageCode(options.language)));
|
|
52
|
+
logger.logTitledMessage('Language specified', specifiedLanguageFormatted);
|
|
53
|
+
}
|
|
54
|
+
const languageCode = normalizeLanguageCode(options.language);
|
|
55
|
+
const shortLanguageCode = getShortLanguageCode(languageCode);
|
|
31
56
|
let transcript;
|
|
32
57
|
let timeline;
|
|
33
58
|
logger.start(`Load ${engine} module`);
|
|
34
59
|
switch (engine) {
|
|
35
|
-
case
|
|
36
|
-
const WhisperSTT = await import(
|
|
60
|
+
case 'whisper': {
|
|
61
|
+
const WhisperSTT = await import('../recognition/WhisperSTT.js');
|
|
37
62
|
const whisperOptions = options.whisper;
|
|
38
|
-
const shortLanguageCode = getShortLanguageCode(language);
|
|
39
|
-
const { modelName, modelDir, tokenizerDir } = await WhisperSTT.loadPackagesAndGetPaths(whisperOptions.model, shortLanguageCode);
|
|
40
|
-
if (shortLanguageCode != "en" && modelName.endsWith(".en")) {
|
|
41
|
-
throw new Error(`The model '${modelName}' is English only and cannot transcribe language '${shortLanguageCode}'`);
|
|
42
|
-
}
|
|
43
63
|
logger.end();
|
|
44
|
-
|
|
64
|
+
const { modelName, modelDir } = await WhisperSTT.loadPackagesAndGetPaths(whisperOptions.model, shortLanguageCode);
|
|
65
|
+
logger.end();
|
|
66
|
+
({ transcript, timeline } = await WhisperSTT.recognize(sourceRawAudio, modelName, modelDir, 'transcribe', shortLanguageCode, whisperOptions));
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
case 'whisper.cpp': {
|
|
70
|
+
const WhisperCppSTT = await import('../recognition/WhisperCppSTT.js');
|
|
71
|
+
const whisperCppOptions = options.whisperCpp;
|
|
72
|
+
logger.end();
|
|
73
|
+
const { modelName, modelPath } = await WhisperCppSTT.loadModelPackage(whisperCppOptions.model, shortLanguageCode);
|
|
74
|
+
logger.end();
|
|
75
|
+
({ transcript, timeline } = await WhisperCppSTT.recognize(sourceRawAudio, 'transcribe', shortLanguageCode, modelName, modelPath, whisperCppOptions));
|
|
45
76
|
break;
|
|
46
77
|
}
|
|
47
|
-
case
|
|
48
|
-
const VoskSTT = await import(
|
|
78
|
+
case 'vosk': {
|
|
79
|
+
const VoskSTT = await import('../recognition/VoskSTT.js');
|
|
49
80
|
try {
|
|
50
81
|
await import('@echogarden/vosk');
|
|
51
82
|
}
|
|
@@ -56,18 +87,17 @@ export async function recognize(input, options) {
|
|
|
56
87
|
const voskOptions = options.vosk;
|
|
57
88
|
const modelPath = voskOptions.modelPath;
|
|
58
89
|
if (!modelPath) {
|
|
59
|
-
throw new Error(
|
|
90
|
+
throw new Error(`Vosk models are not currently auto-downloaded. You'll need to download a model manually and set a model path in 'vosk.modelPath'.`);
|
|
60
91
|
}
|
|
61
92
|
logger.end();
|
|
62
93
|
({ transcript, timeline } = await VoskSTT.recognize(sourceRawAudio, modelPath, true));
|
|
63
94
|
break;
|
|
64
95
|
}
|
|
65
|
-
case
|
|
66
|
-
const SileroSTT = await import(
|
|
96
|
+
case 'silero': {
|
|
97
|
+
const SileroSTT = await import('../recognition/SileroSTT.js');
|
|
67
98
|
const sileroOptions = options.silero;
|
|
68
99
|
let modelPath = sileroOptions.modelPath;
|
|
69
100
|
if (!modelPath) {
|
|
70
|
-
const shortLanguageCode = getShortLanguageCode(language);
|
|
71
101
|
const packageName = SileroSTT.languageCodeToPackageName[shortLanguageCode];
|
|
72
102
|
if (!packageName) {
|
|
73
103
|
throw new Error(`Language '${shortLanguageCode}' is not supported by Silero`);
|
|
@@ -78,72 +108,103 @@ export async function recognize(input, options) {
|
|
|
78
108
|
({ transcript, timeline } = await SileroSTT.recognize(sourceRawAudio, modelPath));
|
|
79
109
|
break;
|
|
80
110
|
}
|
|
81
|
-
case
|
|
82
|
-
const GoogleCloudSTT = await import(
|
|
111
|
+
case 'google-cloud': {
|
|
112
|
+
const GoogleCloudSTT = await import('../recognition/GoogleCloudSTT.js');
|
|
83
113
|
const apiKey = options.googleCloud.apiKey;
|
|
84
114
|
if (!apiKey) {
|
|
85
115
|
throw new Error(`No API key given`);
|
|
86
116
|
}
|
|
87
117
|
logger.end();
|
|
88
|
-
({ transcript, timeline } = await GoogleCloudSTT.recognize(sourceRawAudio, apiKey,
|
|
118
|
+
({ transcript, timeline } = await GoogleCloudSTT.recognize(sourceRawAudio, apiKey, shortLanguageCode));
|
|
89
119
|
break;
|
|
90
120
|
}
|
|
91
|
-
case
|
|
92
|
-
const AzureCognitiveServicesSTT = await import(
|
|
121
|
+
case 'microsoft-azure': {
|
|
122
|
+
const AzureCognitiveServicesSTT = await import('../recognition/AzureCognitiveServicesSTT.js');
|
|
93
123
|
const subscriptionKey = options.microsoftAzure.subscriptionKey;
|
|
94
124
|
if (!subscriptionKey) {
|
|
95
|
-
throw new Error(`No subscription key
|
|
125
|
+
throw new Error(`No Microsoft Azure subscription key provided`);
|
|
96
126
|
}
|
|
97
127
|
const serviceRegion = options.microsoftAzure.serviceRegion;
|
|
98
128
|
if (!serviceRegion) {
|
|
99
|
-
throw new Error(`No service region
|
|
129
|
+
throw new Error(`No Microsoft Azure service region provided`);
|
|
100
130
|
}
|
|
101
131
|
logger.end();
|
|
102
|
-
({ transcript, timeline } = await AzureCognitiveServicesSTT.recognize(sourceRawAudio, subscriptionKey, serviceRegion,
|
|
132
|
+
({ transcript, timeline } = await AzureCognitiveServicesSTT.recognize(sourceRawAudio, subscriptionKey, serviceRegion, shortLanguageCode));
|
|
103
133
|
break;
|
|
104
134
|
}
|
|
105
|
-
case
|
|
106
|
-
const AmazonTranscribeSTT = await import(
|
|
135
|
+
case 'amazon-transcribe': {
|
|
136
|
+
const AmazonTranscribeSTT = await import('../recognition/AmazonTranscribeSTT.js');
|
|
107
137
|
const region = options.amazonTranscribe.region;
|
|
108
138
|
if (!region) {
|
|
109
|
-
throw new Error(`No region
|
|
139
|
+
throw new Error(`No Amazon Transcribe region provided`);
|
|
110
140
|
}
|
|
111
141
|
const accessKeyId = options.amazonTranscribe.accessKeyId;
|
|
112
142
|
if (!accessKeyId) {
|
|
113
|
-
throw new Error(`No access key id
|
|
143
|
+
throw new Error(`No Amazon Transcribe access key id provided`);
|
|
114
144
|
}
|
|
115
145
|
const secretAccessKey = options.amazonTranscribe.secretAccessKey;
|
|
116
146
|
if (!secretAccessKey) {
|
|
117
|
-
throw new Error(`No secret access key
|
|
147
|
+
throw new Error(`No Amazon Transcribe secret access key provided`);
|
|
148
|
+
}
|
|
149
|
+
logger.end();
|
|
150
|
+
({ transcript, timeline } = await AmazonTranscribeSTT.recgonize(sourceRawAudio, shortLanguageCode, region, accessKeyId, secretAccessKey));
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
case 'openai-cloud': {
|
|
154
|
+
const OpenAICloudSTT = await import('../recognition/OpenAICloudSTT.js');
|
|
155
|
+
const openAICloudSTTOptions = options.openAICloud;
|
|
156
|
+
if (!openAICloudSTTOptions.apiKey) {
|
|
157
|
+
throw new Error(`No OpanAI Cloud API key provided`);
|
|
118
158
|
}
|
|
119
159
|
logger.end();
|
|
120
|
-
({ transcript, timeline } = await
|
|
160
|
+
({ transcript, timeline } = await OpenAICloudSTT.recognize(sourceRawAudio, shortLanguageCode, openAICloudSTTOptions));
|
|
121
161
|
break;
|
|
122
162
|
}
|
|
123
163
|
default: {
|
|
124
164
|
throw new Error(`Engine '${options.engine}' is not supported`);
|
|
125
165
|
}
|
|
126
166
|
}
|
|
167
|
+
// If the engine didn't return a timeline, align to get it
|
|
127
168
|
if (!timeline) {
|
|
128
169
|
logger.start(`Align audio to transcript`);
|
|
129
|
-
const alignmentOptions = extendDeep(options.alignment, { language:
|
|
170
|
+
const alignmentOptions = extendDeep(options.alignment, { language: languageCode });
|
|
130
171
|
const { wordTimeline } = await API.align(sourceRawAudio, transcript, alignmentOptions);
|
|
131
172
|
timeline = wordTimeline;
|
|
132
173
|
}
|
|
174
|
+
// If the audio was cropped before recognition, map the timestamps back to the original audio
|
|
175
|
+
if (sourceUncropTimeline && sourceUncropTimeline.length > 0) {
|
|
176
|
+
API.convertCroppedToUncroppedTimeline(timeline, sourceUncropTimeline);
|
|
177
|
+
}
|
|
178
|
+
// Add text offsets
|
|
133
179
|
addWordTextOffsetsToTimeline(timeline, transcript);
|
|
134
|
-
|
|
180
|
+
// Make segment timeline
|
|
181
|
+
const { segmentTimeline } = await wordTimelineToSegmentSentenceTimeline(timeline, transcript, languageCode, 'single', 'preserve');
|
|
135
182
|
logger.end();
|
|
136
183
|
logger.logDuration('Total recognition time', startTimestamp, chalk.magentaBright);
|
|
137
|
-
return {
|
|
184
|
+
return {
|
|
185
|
+
transcript,
|
|
186
|
+
timeline: segmentTimeline,
|
|
187
|
+
wordTimeline: timeline,
|
|
188
|
+
language: languageCode,
|
|
189
|
+
inputRawAudio,
|
|
190
|
+
isolatedRawAudio,
|
|
191
|
+
backgroundRawAudio,
|
|
192
|
+
};
|
|
138
193
|
}
|
|
139
194
|
export const defaultRecognitionOptions = {
|
|
140
|
-
engine:
|
|
195
|
+
engine: 'whisper',
|
|
141
196
|
language: undefined,
|
|
142
197
|
maxAlternatives: 1,
|
|
143
|
-
|
|
144
|
-
|
|
198
|
+
isolate: false,
|
|
199
|
+
crop: true,
|
|
200
|
+
alignment: {},
|
|
201
|
+
languageDetection: {},
|
|
145
202
|
subtitles: defaultSubtitlesBaseConfig,
|
|
146
|
-
|
|
203
|
+
vad: {
|
|
204
|
+
engine: 'adaptive-gate'
|
|
205
|
+
},
|
|
206
|
+
whisper: {},
|
|
207
|
+
whisperCpp: {},
|
|
147
208
|
vosk: {
|
|
148
209
|
modelPath: undefined
|
|
149
210
|
},
|
|
@@ -165,13 +226,20 @@ export const defaultRecognitionOptions = {
|
|
|
165
226
|
region: undefined,
|
|
166
227
|
accessKeyId: undefined,
|
|
167
228
|
secretAccessKey: undefined,
|
|
168
|
-
}
|
|
229
|
+
},
|
|
230
|
+
openAICloud: defaultOpenAICloudSTTOptions
|
|
169
231
|
};
|
|
170
232
|
export const recognitionEngines = [
|
|
171
233
|
{
|
|
172
234
|
id: 'whisper',
|
|
173
235
|
name: 'OpenAI Whisper',
|
|
174
|
-
description: 'A high accuracy transformer-based architecture by OpenAI.',
|
|
236
|
+
description: 'A high accuracy transformer-based speech recognition architecture by OpenAI.',
|
|
237
|
+
type: 'local'
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
id: 'whisper.cpp',
|
|
241
|
+
name: 'OpenAI Whisper (C++ port)',
|
|
242
|
+
description: 'A C++ port of the Whisper speech recognition architecture.',
|
|
175
243
|
type: 'local'
|
|
176
244
|
},
|
|
177
245
|
{
|
|
@@ -204,5 +272,11 @@ export const recognitionEngines = [
|
|
|
204
272
|
description: 'Amazon cloud speech-to-text service.',
|
|
205
273
|
type: 'cloud'
|
|
206
274
|
},
|
|
275
|
+
{
|
|
276
|
+
id: 'openai-cloud',
|
|
277
|
+
name: 'OpenAI Cloud',
|
|
278
|
+
description: 'OpenAI cloud speech-to-text service.',
|
|
279
|
+
type: 'cloud'
|
|
280
|
+
},
|
|
207
281
|
];
|
|
208
282
|
//# sourceMappingURL=Recognition.js.map
|