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