echogarden 1.4.4 → 1.6.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/data/schemas/options.json +310 -25
- package/dist/alignment/DTWMfccSequenceAlignment.d.ts +1 -1
- package/dist/alignment/DTWMfccSequenceAlignment.js +5 -5
- package/dist/alignment/DTWSequenceAlignmentWindowed.js +1 -3
- package/dist/alignment/DTWSequenceAlignmentWindowed.js.map +1 -1
- package/dist/alignment/{TextAlignment.d.ts → SemanticTextAlignment.d.ts} +4 -2
- package/dist/alignment/SemanticTextAlignment.js +336 -0
- package/dist/alignment/SemanticTextAlignment.js.map +1 -0
- package/dist/alignment/SpeechAlignment.d.ts +4 -3
- package/dist/alignment/SpeechAlignment.js +130 -39
- package/dist/alignment/SpeechAlignment.js.map +1 -1
- package/dist/api/API.d.ts +7 -3
- package/dist/api/API.js +7 -2
- package/dist/api/API.js.map +1 -1
- package/dist/api/APIOptions.d.ts +4 -1
- package/dist/api/Alignment.d.ts +1 -1
- package/dist/api/Alignment.js +13 -5
- package/dist/api/Alignment.js.map +1 -1
- package/dist/api/LanguageDetectionCommon.d.ts +6 -0
- package/dist/api/LanguageDetectionCommon.js +2 -0
- package/dist/api/LanguageDetectionCommon.js.map +1 -0
- package/dist/api/Recognition.js.map +1 -1
- package/dist/api/{LanguageDetection.d.ts → SpeechLanguageDetection.d.ts} +1 -25
- package/dist/api/{LanguageDetection.js → SpeechLanguageDetection.js} +1 -68
- package/dist/api/SpeechLanguageDetection.js.map +1 -0
- package/dist/api/{Translation.js → SpeechTranslation.js} +3 -3
- package/dist/api/SpeechTranslation.js.map +1 -0
- package/dist/api/Synthesis.d.ts +0 -1
- package/dist/api/Synthesis.js +4 -4
- package/dist/api/TextLanguageDetection.d.ts +21 -0
- package/dist/api/TextLanguageDetection.js +67 -0
- package/dist/api/TextLanguageDetection.js.map +1 -0
- package/dist/api/TextTranslation.d.ts +25 -0
- package/dist/api/TextTranslation.js +101 -0
- package/dist/api/TextTranslation.js.map +1 -0
- package/dist/api/TimelineTranslationAlignment.d.ts +23 -0
- package/dist/api/TimelineTranslationAlignment.js +92 -0
- package/dist/api/TimelineTranslationAlignment.js.map +1 -0
- package/dist/api/TranscriptAndTranslationAlignment.d.ts +35 -0
- package/dist/api/TranscriptAndTranslationAlignment.js +78 -0
- package/dist/api/TranscriptAndTranslationAlignment.js.map +1 -0
- package/dist/api/TranslationAlignment.d.ts +4 -3
- package/dist/api/TranslationAlignment.js +9 -8
- package/dist/api/TranslationAlignment.js.map +1 -1
- package/dist/api/VoiceActivityDetection.js +16 -1
- package/dist/api/VoiceActivityDetection.js.map +1 -1
- package/dist/audio/AudioBufferConversion.d.ts +0 -1
- package/dist/audio/AudioPlayer.d.ts +0 -1
- package/dist/audio/AudioPlayer.js +62 -41
- package/dist/audio/AudioPlayer.js.map +1 -1
- package/dist/audio/AudioUtilities.d.ts +0 -1
- package/dist/cli/CLI.d.ts +28 -7
- package/dist/cli/CLI.js +265 -37
- package/dist/cli/CLI.js.map +1 -1
- package/dist/codecs/FFMpegTranscoder.d.ts +0 -1
- package/dist/codecs/FFMpegTranscoder.js +7 -0
- package/dist/codecs/FFMpegTranscoder.js.map +1 -1
- package/dist/codecs/TIMITCodec.d.ts +0 -1
- package/dist/codecs/WaveCodec.d.ts +0 -1
- package/dist/dsp/FFT.d.ts +1 -1
- package/dist/dsp/FFT.js +6 -0
- package/dist/dsp/FFT.js.map +1 -1
- package/dist/dsp/KWeightingFilter.js +1 -1
- package/dist/dsp/KWeightingFilter.js.map +1 -1
- package/dist/dsp/MelSpectogram.d.ts +3 -2
- package/dist/dsp/MelSpectogram.js +14 -8
- package/dist/dsp/MelSpectogram.js.map +1 -1
- package/dist/math/VectorMath.d.ts +9 -9
- package/dist/math/VectorMath.js +10 -10
- package/dist/math/VectorMath.js.map +1 -1
- package/dist/nlp/ChineseSegmentation.js +4 -4
- package/dist/nlp/ChineseSegmentation.js.map +1 -1
- package/dist/nlp/Segmentation.d.ts +2 -2
- package/dist/nlp/Segmentation.js +20 -13
- package/dist/nlp/Segmentation.js.map +1 -1
- package/dist/recognition/OpenAICloudSTT.d.ts +2 -1
- package/dist/recognition/OpenAICloudSTT.js +30 -19
- package/dist/recognition/OpenAICloudSTT.js.map +1 -1
- package/dist/recognition/SileroSTT.d.ts +0 -1
- package/dist/recognition/WhisperCppSTT.d.ts +3 -3
- package/dist/recognition/WhisperCppSTT.js +21 -9
- package/dist/recognition/WhisperCppSTT.js.map +1 -1
- package/dist/recognition/WhisperSTT.d.ts +9 -6
- package/dist/recognition/WhisperSTT.js +227 -46
- package/dist/recognition/WhisperSTT.js.map +1 -1
- package/dist/server/Client.d.ts +3 -4
- package/dist/server/Client.js.map +1 -1
- package/dist/server/Worker.d.ts +3 -3
- package/dist/server/Worker.js +3 -2
- package/dist/server/Worker.js.map +1 -1
- package/dist/source-separation/MDXNetSourceSeparation.d.ts +0 -1
- package/dist/source-separation/MDXNetSourceSeparation.js +1 -1
- package/dist/source-separation/MDXNetSourceSeparation.js.map +1 -1
- package/dist/speech-embeddings/WavToVec2BertFeatureEmbeddings.d.ts +12 -0
- package/dist/speech-embeddings/WavToVec2BertFeatureEmbeddings.js +68 -0
- package/dist/speech-embeddings/WavToVec2BertFeatureEmbeddings.js.map +1 -0
- package/dist/speech-language-detection/SileroLanguageDetection.d.ts +1 -2
- package/dist/speech-language-detection/SileroLanguageDetection.js +1 -1
- package/dist/speech-language-detection/SileroLanguageDetection.js.map +1 -1
- package/dist/subtitles/Subtitles.js +2 -2
- package/dist/subtitles/Subtitles.js.map +1 -1
- package/dist/synthesis/GoogleCloudTTS.d.ts +0 -1
- package/dist/synthesis/GoogleTranslateTTS.d.ts +0 -1
- package/dist/synthesis/GoogleTranslateTTS.js +6 -21
- package/dist/synthesis/GoogleTranslateTTS.js.map +1 -1
- package/dist/synthesis/StreamlabsPollyTTS.d.ts +0 -1
- package/dist/synthesis/VitsTTS.d.ts +0 -1
- package/dist/synthesis/VitsTTS.js +30 -0
- package/dist/synthesis/VitsTTS.js.map +1 -1
- package/dist/tests/Test.js +0 -31
- package/dist/tests/Test.js.map +1 -1
- package/dist/text-language-detection/FastTextLanguageDetection.d.ts +1 -1
- package/dist/text-language-detection/FastTextLanguageDetection.js.map +1 -1
- package/dist/text-language-detection/TinyLDLanguageDetection.d.ts +1 -1
- package/dist/text-language-detection/TinyLDLanguageDetection.js.map +1 -1
- package/dist/text-translation/DeepLTextTranslation.d.ts +2 -0
- package/dist/text-translation/DeepLTextTranslation.js +67 -0
- package/dist/text-translation/DeepLTextTranslation.js.map +1 -0
- package/dist/text-translation/GoogleTranslateTextTranslation.d.ts +10 -0
- package/dist/text-translation/GoogleTranslateTextTranslation.js +554 -0
- package/dist/text-translation/GoogleTranslateTextTranslation.js.map +1 -0
- package/dist/text-translation/NLLBTextTranslation.d.ts +2 -1
- package/dist/text-translation/NLLBTextTranslation.js +249 -19
- package/dist/text-translation/NLLBTextTranslation.js.map +1 -1
- package/dist/utilities/BinaryArrayConversion.d.ts +0 -1
- package/dist/utilities/BrowserRequestHeaders.d.ts +6 -0
- package/dist/utilities/BrowserRequestHeaders.js +52 -0
- package/dist/utilities/BrowserRequestHeaders.js.map +1 -0
- package/dist/utilities/BufferFileReadStream.d.ts +20 -0
- package/dist/utilities/BufferFileReadStream.js +81 -0
- package/dist/utilities/BufferFileReadStream.js.map +1 -0
- package/dist/utilities/DynamicUint8Array.d.ts +9 -0
- package/dist/utilities/DynamicUint8Array.js +31 -0
- package/dist/utilities/DynamicUint8Array.js.map +1 -0
- package/dist/utilities/FileSystem.d.ts +0 -2
- package/dist/utilities/Hashing.d.ts +3 -10
- package/dist/utilities/Hashing.js +10 -127
- package/dist/utilities/Hashing.js.map +1 -1
- package/dist/utilities/LEB128.d.ts +15 -5
- package/dist/utilities/LEB128.js +199 -119
- package/dist/utilities/LEB128.js.map +1 -1
- package/dist/utilities/LPVarInt.d.ts +11 -0
- package/dist/utilities/LPVarInt.js +187 -0
- package/dist/utilities/LPVarInt.js.map +1 -0
- package/dist/utilities/Locale.d.ts +1 -1
- package/dist/utilities/Locale.js +1 -1
- package/dist/utilities/OnnxUtilities.d.ts +1 -2
- package/dist/utilities/PVarInt.d.ts +4 -0
- package/dist/utilities/PVarInt.js +166 -0
- package/dist/utilities/PVarInt.js.map +1 -0
- package/dist/utilities/PackageManager.js +48 -25
- package/dist/utilities/PackageManager.js.map +1 -1
- package/dist/utilities/RandomGenerator.d.ts +3 -17
- package/dist/utilities/RandomGenerator.js +12 -81
- package/dist/utilities/RandomGenerator.js.map +1 -1
- package/dist/utilities/Timeline.d.ts +2 -0
- package/dist/utilities/Timeline.js +129 -20
- package/dist/utilities/Timeline.js.map +1 -1
- package/dist/utilities/Utilities.d.ts +1 -3
- package/dist/utilities/Utilities.js +30 -3
- package/dist/utilities/Utilities.js.map +1 -1
- package/dist/utilities/VarInt.d.ts +4 -0
- package/dist/utilities/VarInt.js +166 -0
- package/dist/utilities/VarInt.js.map +1 -0
- package/dist/utilities/VirtualFileReadStream.d.ts +20 -0
- package/dist/utilities/VirtualFileReadStream.js +79 -0
- package/dist/utilities/VirtualFileReadStream.js.map +1 -0
- package/dist/utilities/WebReader.js +7 -23
- package/dist/utilities/WebReader.js.map +1 -1
- package/dist/voice-activity-detection/SileroVAD.d.ts +0 -1
- package/docs/API.md +105 -3
- package/docs/CLI.md +51 -1
- package/docs/Engines.md +32 -3
- package/docs/Options.md +53 -12
- package/docs/Tasklist.md +1 -13
- package/package.json +20 -24
- package/src/alignment/DTWMfccSequenceAlignment.ts +5 -5
- package/src/alignment/DTWSequenceAlignmentWindowed.ts +1 -3
- package/src/alignment/SemanticTextAlignment.ts +467 -0
- package/src/alignment/SpeechAlignment.ts +214 -56
- package/src/api/API.ts +18 -2
- package/src/api/APIOptions.ts +14 -1
- package/src/api/Alignment.ts +31 -9
- package/src/api/LanguageDetectionCommon.ts +7 -0
- package/src/api/Recognition.ts +2 -0
- package/src/api/{LanguageDetection.ts → SpeechLanguageDetection.ts} +1 -119
- package/src/api/{Translation.ts → SpeechTranslation.ts} +2 -2
- package/src/api/Synthesis.ts +4 -4
- package/src/api/TextLanguageDetection.ts +116 -0
- package/src/api/TextTranslation.ts +177 -0
- package/src/api/TimelineTranslationAlignment.ts +162 -0
- package/src/api/TranscriptAndTranslationAlignment.ts +164 -0
- package/src/api/TranslationAlignment.ts +12 -10
- package/src/api/VoiceActivityDetection.ts +24 -3
- package/src/audio/AudioPlayer.ts +2 -0
- package/src/cli/CLI.ts +376 -40
- package/src/codecs/FFMpegTranscoder.ts +6 -0
- package/src/dsp/FFT.ts +8 -2
- package/src/dsp/KWeightingFilter.ts +1 -1
- package/src/dsp/MelSpectogram.ts +17 -8
- package/src/math/VectorMath.ts +15 -15
- package/src/nlp/ChineseSegmentation.ts +6 -4
- package/src/nlp/Segmentation.ts +18 -13
- package/src/recognition/OpenAICloudSTT.ts +47 -29
- package/src/recognition/WhisperCppSTT.ts +26 -11
- package/src/recognition/WhisperSTT.ts +364 -49
- package/src/server/Client.ts +3 -2
- package/src/server/Worker.ts +3 -2
- package/src/source-separation/MDXNetSourceSeparation.ts +1 -1
- package/src/speech-embeddings/WavToVec2BertFeatureEmbeddings.ts +107 -0
- package/src/speech-language-detection/SileroLanguageDetection.ts +2 -1
- package/src/subtitles/Subtitles.ts +2 -2
- package/src/synthesis/GoogleTranslateTTS.ts +7 -21
- package/src/synthesis/VitsTTS.ts +31 -3
- package/src/tests/Test.ts +1 -38
- package/src/text-language-detection/FastTextLanguageDetection.ts +1 -1
- package/src/text-language-detection/TinyLDLanguageDetection.ts +1 -1
- package/src/text-translation/DeepLTextTranslation.ts +88 -0
- package/src/text-translation/GoogleTranslateTextTranslation.ts +667 -0
- package/src/text-translation/NLLBTextTranslation.ts +261 -21
- package/src/typings/Fillers.d.ts +25 -2
- package/src/utilities/BrowserRequestHeaders.ts +59 -0
- package/src/utilities/DynamicUint8Array.ts +39 -0
- package/src/utilities/Hashing.ts +14 -167
- package/src/utilities/LEB128.ts +273 -148
- package/src/utilities/LPVarInt.ts +292 -0
- package/src/utilities/Locale.ts +1 -1
- package/src/utilities/OnnxUtilities.ts +1 -1
- package/src/utilities/PackageManager.ts +51 -30
- package/src/utilities/RandomGenerator.ts +12 -113
- package/src/utilities/Timeline.ts +162 -23
- package/src/utilities/Utilities.ts +40 -3
- package/src/utilities/VirtualFileReadStream.ts +109 -0
- package/src/utilities/WebReader.ts +9 -23
- package/dist/alignment/TextAlignment.js +0 -156
- package/dist/alignment/TextAlignment.js.map +0 -1
- package/dist/api/LanguageDetection.js.map +0 -1
- package/dist/api/Translation.js.map +0 -1
- package/src/alignment/TextAlignment.ts +0 -234
- /package/dist/api/{Translation.d.ts → SpeechTranslation.d.ts} +0 -0
package/src/cli/CLI.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import * as API from '../api/API.js'
|
|
2
2
|
import { parseCLIArguments } from './CLIParser.js'
|
|
3
|
-
import {
|
|
3
|
+
import { convertHtmlToText, formatIntegerWithLeadingZeros, formatListWithQuotedElements, getWithDefault, logToStderr, setupUnhandledExceptionListeners, splitFilenameOnExtendedExtension, stringifyAndFormatJson } from '../utilities/Utilities.js'
|
|
4
4
|
import { getOptionTypeFromSchema, SchemaTypeDefinition } from './CLIOptionsSchema.js'
|
|
5
5
|
import { ParsedConfigFile, parseConfigFile, parseJSONConfigFile } from './CLIConfigFile.js'
|
|
6
6
|
|
|
7
7
|
import chalk from 'chalk'
|
|
8
8
|
import { RawAudio, applyGainDecibels, encodeRawAudioToWave, getEmptyRawAudio, getRawAudioDuration, normalizeAudioLevel, sliceRawAudioByTime } from '../audio/AudioUtilities.js'
|
|
9
|
-
import { SubtitlesConfig, subtitlesToText,
|
|
9
|
+
import { SubtitlesConfig, subtitlesToText, timelineToSubtitles } from '../subtitles/Subtitles.js'
|
|
10
10
|
import { Logger, resetActiveLogger } from '../utilities/Logger.js'
|
|
11
11
|
import { isMainThread, parentPort } from 'node:worker_threads'
|
|
12
12
|
import { encodeFromChannels, getDefaultFFMpegOptionsForSpeech } from '../codecs/FFMpegTranscoder.js'
|
|
@@ -219,19 +219,25 @@ const help = [
|
|
|
219
219
|
`${executableName} ${chalk.magentaBright('speak-url')} url [output files...] [options...]`,
|
|
220
220
|
` Speak the HTML document on the given URL\n`,
|
|
221
221
|
`${executableName} ${chalk.magentaBright('speak-wikipedia')} articleName [output files...] [options...]`,
|
|
222
|
-
` Speak the given
|
|
222
|
+
` Speak the given Wikipedia article. Language edition can be specified by --language=<langCode>\n`,
|
|
223
223
|
`${executableName} ${chalk.magentaBright('transcribe')} audioFile [output files...] [options...]`,
|
|
224
|
-
` Transcribe audio file\n`,
|
|
225
|
-
`${executableName} ${chalk.magentaBright('align')} audioFile
|
|
226
|
-
` Align audio file to
|
|
227
|
-
`${executableName} ${chalk.magentaBright('translate-
|
|
228
|
-
`
|
|
229
|
-
`${executableName} ${chalk.magentaBright('
|
|
230
|
-
`
|
|
231
|
-
`${executableName} ${chalk.magentaBright('
|
|
232
|
-
`
|
|
224
|
+
` Transcribe a spoken audio file\n`,
|
|
225
|
+
`${executableName} ${chalk.magentaBright('align')} audioFile transcriptFile [output files...] [options...]`,
|
|
226
|
+
` Align spoken audio file to its transcript\n`,
|
|
227
|
+
`${executableName} ${chalk.magentaBright('translate-text')} inputFile [output files...] [options...]`,
|
|
228
|
+
` Translate text to a different language\n`,
|
|
229
|
+
`${executableName} ${chalk.magentaBright('translate-speech')} audioFile [output files...] [options...]`,
|
|
230
|
+
` Transcribe spoken audio file directly to a different language\n`,
|
|
231
|
+
`${executableName} ${chalk.magentaBright('align-translation')} audioFile translatedTranscriptFile [output files...] [options...]`,
|
|
232
|
+
` Align spoken audio file to its translated transcript\n`,
|
|
233
|
+
`${executableName} ${chalk.magentaBright('align-transcript-and-translation')} audioFile transcriptFile translatedTranscriptFile [output files...] [options...]`,
|
|
234
|
+
` Align spoken audio file to both its transcript and its translated transcript using a two-stage approach.\n`,
|
|
235
|
+
`${executableName} ${chalk.magentaBright('align-timeline-translation')} timelineFile translatedFile [output files...] [options...]`,
|
|
236
|
+
` Align a given timeline file to its translated text\n`,
|
|
233
237
|
`${executableName} ${chalk.magentaBright('detect-text-language')} inputFile [output files...] [options...]`,
|
|
234
238
|
` Detect language of textual file\n`,
|
|
239
|
+
`${executableName} ${chalk.magentaBright('detect-speech-language')} audioFile [output files...] [options...]`,
|
|
240
|
+
` Detect language of spoken audio file\n`,
|
|
235
241
|
`${executableName} ${chalk.magentaBright('detect-voice-activity')} audioFile [output files...] [options...]`,
|
|
236
242
|
` Detect voice activity in audio file\n`,
|
|
237
243
|
`${executableName} ${chalk.magentaBright('denoise')} audioFile [output files...] [options...]`,
|
|
@@ -275,6 +281,11 @@ async function startWithArgs(operationData: CLIOperationData) {
|
|
|
275
281
|
break
|
|
276
282
|
}
|
|
277
283
|
|
|
284
|
+
case 'translate-text': {
|
|
285
|
+
await translateText(operationData)
|
|
286
|
+
break
|
|
287
|
+
}
|
|
288
|
+
|
|
278
289
|
case 'translate-speech': {
|
|
279
290
|
await translateSpeech(operationData)
|
|
280
291
|
break
|
|
@@ -285,6 +296,16 @@ async function startWithArgs(operationData: CLIOperationData) {
|
|
|
285
296
|
break
|
|
286
297
|
}
|
|
287
298
|
|
|
299
|
+
case 'align-transcript-and-translation': {
|
|
300
|
+
await alignTranscriptAndTranslation(operationData)
|
|
301
|
+
break
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
case 'align-timeline-translation': {
|
|
305
|
+
await alignTimelineTranslation(operationData)
|
|
306
|
+
break
|
|
307
|
+
}
|
|
308
|
+
|
|
288
309
|
case 'detect-language': {
|
|
289
310
|
await detectLanguage(operationData, 'auto')
|
|
290
311
|
break
|
|
@@ -352,7 +373,7 @@ async function startWithArgs(operationData: CLIOperationData) {
|
|
|
352
373
|
}
|
|
353
374
|
}
|
|
354
375
|
|
|
355
|
-
async function speak(operationData: CLIOperationData) {
|
|
376
|
+
export async function speak(operationData: CLIOperationData) {
|
|
356
377
|
const logger = new Logger()
|
|
357
378
|
|
|
358
379
|
const { operationArgs, operation, operationOptionsLookup, cliOptions } = operationData
|
|
@@ -424,8 +445,8 @@ async function speak(operationData: CLIOperationData) {
|
|
|
424
445
|
textSegments = splitToParagraphs(textContent, 'single', 'preserve')
|
|
425
446
|
} else if (sourceFileExtension == 'srt' || sourceFileExtension == 'vtt') {
|
|
426
447
|
const fileContent = await readFile(sourceFile, { encoding: 'utf-8' })
|
|
427
|
-
textSegments = subtitlesToTimeline(fileContent).map(entry => entry.text)
|
|
428
|
-
|
|
448
|
+
//textSegments = subtitlesToTimeline(fileContent).map(entry => entry.text)
|
|
449
|
+
textSegments = [subtitlesToText(fileContent)]
|
|
429
450
|
} else if (sourceFileExtension == 'xml' || sourceFileExtension == 'ssml') {
|
|
430
451
|
options.ssml = true
|
|
431
452
|
textSegments = [fileContent]
|
|
@@ -510,7 +531,7 @@ async function speak(operationData: CLIOperationData) {
|
|
|
510
531
|
logger.end()
|
|
511
532
|
}
|
|
512
533
|
|
|
513
|
-
async function transcribe(operationData: CLIOperationData) {
|
|
534
|
+
export async function transcribe(operationData: CLIOperationData) {
|
|
514
535
|
const logger = new Logger()
|
|
515
536
|
|
|
516
537
|
const { operationArgs, operationOptionsLookup, cliOptions } = operationData
|
|
@@ -572,7 +593,7 @@ async function transcribe(operationData: CLIOperationData) {
|
|
|
572
593
|
}
|
|
573
594
|
}
|
|
574
595
|
|
|
575
|
-
async function align(operationData: CLIOperationData) {
|
|
596
|
+
export async function align(operationData: CLIOperationData) {
|
|
576
597
|
const logger = new Logger()
|
|
577
598
|
|
|
578
599
|
const { operationArgs, operationOptionsLookup, cliOptions } = operationData
|
|
@@ -668,7 +689,7 @@ async function align(operationData: CLIOperationData) {
|
|
|
668
689
|
}
|
|
669
690
|
}
|
|
670
691
|
|
|
671
|
-
async function alignTranslation(operationData: CLIOperationData) {
|
|
692
|
+
export async function alignTranslation(operationData: CLIOperationData) {
|
|
672
693
|
const logger = new Logger()
|
|
673
694
|
|
|
674
695
|
const { operationArgs, operationOptionsLookup, cliOptions } = operationData
|
|
@@ -677,7 +698,7 @@ async function alignTranslation(operationData: CLIOperationData) {
|
|
|
677
698
|
const outputFilenames = operationArgs.slice(2)
|
|
678
699
|
|
|
679
700
|
if (audioFilename == undefined) {
|
|
680
|
-
throw new Error(`align-translation requires
|
|
701
|
+
throw new Error(`align-translation requires a first argument containing the audio file path.`)
|
|
681
702
|
}
|
|
682
703
|
|
|
683
704
|
if (!existsSync(audioFilename)) {
|
|
@@ -706,7 +727,7 @@ async function alignTranslation(operationData: CLIOperationData) {
|
|
|
706
727
|
} else if (referenceFileExtension == 'srt' || referenceFileExtension == 'vtt') {
|
|
707
728
|
text = subtitlesToText(fileContent)
|
|
708
729
|
} else {
|
|
709
|
-
throw new Error(`align only supports reference files with extensions 'txt', 'html', 'htm', 'srt' or 'vtt'`)
|
|
730
|
+
throw new Error(`align-translation only supports reference files with extensions 'txt', 'html', 'htm', 'srt' or 'vtt'`)
|
|
710
731
|
}
|
|
711
732
|
|
|
712
733
|
if (cliOptions.play == null) {
|
|
@@ -721,8 +742,9 @@ async function alignTranslation(operationData: CLIOperationData) {
|
|
|
721
742
|
const {
|
|
722
743
|
timeline,
|
|
723
744
|
wordTimeline,
|
|
724
|
-
|
|
725
|
-
|
|
745
|
+
translatedTranscript,
|
|
746
|
+
sourceLanguage,
|
|
747
|
+
targetLanguage,
|
|
726
748
|
inputRawAudio,
|
|
727
749
|
isolatedRawAudio,
|
|
728
750
|
backgroundRawAudio } = await API.alignTranslation(audioFilename, text, options)
|
|
@@ -737,10 +759,139 @@ async function alignTranslation(operationData: CLIOperationData) {
|
|
|
737
759
|
const segmentAudio = sliceRawAudioByTime(inputRawAudio, segmentEntry.startTime, segmentEntry.endTime)
|
|
738
760
|
const sentenceTimeline = addTimeOffsetToTimeline(segmentEntry.timeline!, -segmentEntry.startTime)
|
|
739
761
|
|
|
740
|
-
await writeOutputFilesForSegment(outputFilenames, segmentIndex, timeline.length, segmentAudio, sentenceTimeline, segmentEntry.text,
|
|
762
|
+
await writeOutputFilesForSegment(outputFilenames, segmentIndex, timeline.length, segmentAudio, sentenceTimeline, segmentEntry.text, targetLanguage, allowOverwrite)
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
for (const outputFilename of outputFilenames) {
|
|
767
|
+
const partPatternMatch = outputFilename.match(filenamePlaceholderPattern)
|
|
768
|
+
|
|
769
|
+
if (partPatternMatch) {
|
|
770
|
+
continue
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
const fileSaver = getFileSaver(outputFilename, allowOverwrite)
|
|
774
|
+
|
|
775
|
+
await fileSaver(inputRawAudio, timeline, translatedTranscript, options.subtitles)
|
|
776
|
+
|
|
777
|
+
await writeSourceSeparationOutputIfNeeded(outputFilename, isolatedRawAudio, backgroundRawAudio, allowOverwrite, true)
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
logger.end()
|
|
781
|
+
|
|
782
|
+
if (cliOptions.play) {
|
|
783
|
+
let audioToPlay: RawAudio
|
|
784
|
+
|
|
785
|
+
if (isolatedRawAudio) {
|
|
786
|
+
audioToPlay = isolatedRawAudio
|
|
787
|
+
} else {
|
|
788
|
+
audioToPlay = inputRawAudio
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
const normalizedAudioToPlay = normalizeAudioLevel(audioToPlay)
|
|
792
|
+
|
|
793
|
+
await playAudioWithWordTimeline(normalizedAudioToPlay, wordTimeline, translatedTranscript)
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
export async function alignTranscriptAndTranslation(operationData: CLIOperationData) {
|
|
798
|
+
const logger = new Logger()
|
|
799
|
+
|
|
800
|
+
const { operationArgs, operationOptionsLookup, cliOptions } = operationData
|
|
801
|
+
|
|
802
|
+
const audioFilename = operationArgs[0]
|
|
803
|
+
const outputFilenames = operationArgs.slice(3)
|
|
804
|
+
|
|
805
|
+
if (audioFilename == undefined) {
|
|
806
|
+
throw new Error(`align-transcript-and-translation requires a first argument containing the audio file path.`)
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
if (!existsSync(audioFilename)) {
|
|
810
|
+
throw new Error(`The given source file '${audioFilename}' was not found.`)
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
const nativeTranscriptFilePath = operationArgs[1]
|
|
814
|
+
|
|
815
|
+
if (nativeTranscriptFilePath == undefined) {
|
|
816
|
+
throw new Error(`align-transcript-and-translation requires a second argument containing the native language transcript file path.`)
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
if (!existsSync(nativeTranscriptFilePath)) {
|
|
820
|
+
throw new Error(`The given transcript file '${nativeTranscriptFilePath}' was not found.`)
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
const translatedTranscriptFilePath = operationArgs[2]
|
|
824
|
+
|
|
825
|
+
if (translatedTranscriptFilePath == undefined) {
|
|
826
|
+
throw new Error(`align-transcript-and-translation requires a third argument containing the translated language transcript file path.`)
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
if (!existsSync(translatedTranscriptFilePath)) {
|
|
830
|
+
throw new Error(`The given translated transcript file '${nativeTranscriptFilePath}' was not found.`)
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
let transcript: string
|
|
834
|
+
|
|
835
|
+
{
|
|
836
|
+
const nativeTranscriptFileExtension = getLowercaseFileExtension(nativeTranscriptFilePath)
|
|
837
|
+
const fileContent = await readFile(nativeTranscriptFilePath, { encoding: 'utf-8' })
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
if (nativeTranscriptFileExtension == 'txt') {
|
|
841
|
+
transcript = fileContent
|
|
842
|
+
} else if (nativeTranscriptFileExtension == 'html' || nativeTranscriptFileExtension == 'htm') {
|
|
843
|
+
transcript = await convertHtmlToText(fileContent)
|
|
844
|
+
} else if (nativeTranscriptFileExtension == 'srt' || nativeTranscriptFileExtension == 'vtt') {
|
|
845
|
+
transcript = subtitlesToText(fileContent)
|
|
846
|
+
} else {
|
|
847
|
+
throw new Error(`align-transcript-and-translation only supports transcript files with extensions 'txt', 'html', 'htm', 'srt' or 'vtt'`)
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
let translatedTranscript: string
|
|
852
|
+
|
|
853
|
+
{
|
|
854
|
+
const translatedTranscriptFileExtension = getLowercaseFileExtension(translatedTranscriptFilePath)
|
|
855
|
+
const fileContent = await readFile(translatedTranscriptFilePath, { encoding: 'utf-8' })
|
|
856
|
+
|
|
857
|
+
if (translatedTranscriptFileExtension == 'txt') {
|
|
858
|
+
translatedTranscript = fileContent
|
|
859
|
+
} else if (translatedTranscriptFileExtension == 'html' || translatedTranscriptFileExtension == 'htm') {
|
|
860
|
+
translatedTranscript = await convertHtmlToText(fileContent)
|
|
861
|
+
} else if (translatedTranscriptFileExtension == 'srt' || translatedTranscriptFileExtension == 'vtt') {
|
|
862
|
+
translatedTranscript = subtitlesToText(fileContent)
|
|
863
|
+
} else {
|
|
864
|
+
throw new Error(`align-transcript-and-translation only supports transcript files with extensions 'txt', 'html', 'htm', 'srt' or 'vtt'`)
|
|
741
865
|
}
|
|
742
866
|
}
|
|
743
867
|
|
|
868
|
+
if (cliOptions.play == null) {
|
|
869
|
+
cliOptions.play = outputFilenames.length === 0
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
const options = await optionsLookupToTypedObject(operationOptionsLookup, 'TranscriptAndTranslationAlignmentOptions')
|
|
873
|
+
|
|
874
|
+
const allowOverwrite = getWithDefault(cliOptions.overwrite, overwriteByDefault)
|
|
875
|
+
const { includesPlaceholderPattern } = await checkOutputFilenames(outputFilenames, true, true, true)
|
|
876
|
+
|
|
877
|
+
const {
|
|
878
|
+
timeline,
|
|
879
|
+
wordTimeline,
|
|
880
|
+
|
|
881
|
+
translatedTimeline,
|
|
882
|
+
translatedWordTimeline,
|
|
883
|
+
|
|
884
|
+
sourceLanguage,
|
|
885
|
+
targetLanguage,
|
|
886
|
+
|
|
887
|
+
inputRawAudio,
|
|
888
|
+
isolatedRawAudio,
|
|
889
|
+
backgroundRawAudio } = await API.alignTranscriptAndTranslation(audioFilename, transcript, translatedTranscript, options)
|
|
890
|
+
|
|
891
|
+
if (outputFilenames.length > 0) {
|
|
892
|
+
logger.start('\nWrite output files')
|
|
893
|
+
}
|
|
894
|
+
|
|
744
895
|
for (const outputFilename of outputFilenames) {
|
|
745
896
|
const partPatternMatch = outputFilename.match(filenamePlaceholderPattern)
|
|
746
897
|
|
|
@@ -753,6 +904,16 @@ async function alignTranslation(operationData: CLIOperationData) {
|
|
|
753
904
|
await fileSaver(inputRawAudio, timeline, transcript, options.subtitles)
|
|
754
905
|
|
|
755
906
|
await writeSourceSeparationOutputIfNeeded(outputFilename, isolatedRawAudio, backgroundRawAudio, allowOverwrite, true)
|
|
907
|
+
|
|
908
|
+
const fileExtension = getLowercaseFileExtension(outputFilename)
|
|
909
|
+
|
|
910
|
+
if (['json', 'txt', 'srt', 'vtt'].includes(fileExtension)) {
|
|
911
|
+
const pathWithoutExtension = outputFilename.substring(0, outputFilename.lastIndexOf('.'))
|
|
912
|
+
const translatedOutputPath = `${pathWithoutExtension}.translated.${fileExtension}`
|
|
913
|
+
|
|
914
|
+
const translatedFileSaver = getFileSaver(translatedOutputPath, allowOverwrite)
|
|
915
|
+
await translatedFileSaver(inputRawAudio, translatedTimeline, translatedTranscript, options.subtitles)
|
|
916
|
+
}
|
|
756
917
|
}
|
|
757
918
|
|
|
758
919
|
logger.end()
|
|
@@ -768,11 +929,168 @@ async function alignTranslation(operationData: CLIOperationData) {
|
|
|
768
929
|
|
|
769
930
|
const normalizedAudioToPlay = normalizeAudioLevel(audioToPlay)
|
|
770
931
|
|
|
771
|
-
await playAudioWithWordTimeline(normalizedAudioToPlay,
|
|
932
|
+
await playAudioWithWordTimeline(normalizedAudioToPlay, translatedWordTimeline, translatedTranscript)
|
|
772
933
|
}
|
|
773
934
|
}
|
|
774
935
|
|
|
775
|
-
async function
|
|
936
|
+
export async function alignTimelineTranslation(operationData: CLIOperationData) {
|
|
937
|
+
const logger = new Logger()
|
|
938
|
+
|
|
939
|
+
const { operationArgs, operationOptionsLookup, cliOptions } = operationData
|
|
940
|
+
|
|
941
|
+
const timelineFilename = operationArgs[0]
|
|
942
|
+
const outputFilenames = operationArgs.slice(2)
|
|
943
|
+
|
|
944
|
+
if (timelineFilename == undefined) {
|
|
945
|
+
throw new Error(`align-timeline-translation requires a first argument containing the timeline file path.`)
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
if (getLowercaseFileExtension(timelineFilename) != 'json') {
|
|
949
|
+
throw new Error(`align-timeline-translation only supports timeline files with extension 'json'`)
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
if (!existsSync(timelineFilename)) {
|
|
953
|
+
throw new Error(`The given timeline file '${timelineFilename}' was not found.`)
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
const timeline = await readAndParseJsonFile(timelineFilename) as Timeline
|
|
957
|
+
|
|
958
|
+
const translationFilePath = operationArgs[1]
|
|
959
|
+
|
|
960
|
+
if (translationFilePath == undefined) {
|
|
961
|
+
throw new Error(`align-timeline-translation requires a second argument containing the translated reference file path.`)
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
if (!existsSync(translationFilePath)) {
|
|
965
|
+
throw new Error(`The given reference file '${translationFilePath}' was not found.`)
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
const translationFileExtension = getLowercaseFileExtension(translationFilePath)
|
|
969
|
+
const translationFileContent = await readFile(translationFilePath, { encoding: 'utf-8' })
|
|
970
|
+
|
|
971
|
+
let translationText: string
|
|
972
|
+
|
|
973
|
+
if (translationFileExtension == 'txt') {
|
|
974
|
+
translationText = translationFileContent
|
|
975
|
+
} else if (translationFileExtension == 'html' || translationFileExtension == 'htm') {
|
|
976
|
+
translationText = await convertHtmlToText(translationFileContent)
|
|
977
|
+
} else if (translationFileExtension == 'srt' || translationFileExtension == 'vtt') {
|
|
978
|
+
translationText = subtitlesToText(translationFileContent)
|
|
979
|
+
} else {
|
|
980
|
+
throw new Error(`align only supports reference files with extensions 'txt', 'html', 'htm', 'srt' or 'vtt'`)
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
const options = await optionsLookupToTypedObject(operationOptionsLookup, 'TimelineTranslationAlignmentOptions')
|
|
984
|
+
|
|
985
|
+
const {
|
|
986
|
+
timeline: translationTimeline,
|
|
987
|
+
wordTimeline: translationWordTimeline,
|
|
988
|
+
rawAudio
|
|
989
|
+
} = await API.alignTimelineTranslation(timeline, translationText, options)
|
|
990
|
+
|
|
991
|
+
if (outputFilenames.length > 0) {
|
|
992
|
+
logger.start('\nWrite output files')
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
const allowOverwrite = getWithDefault(cliOptions.overwrite, overwriteByDefault)
|
|
996
|
+
|
|
997
|
+
for (const outputFilename of outputFilenames) {
|
|
998
|
+
const partPatternMatch = outputFilename.match(filenamePlaceholderPattern)
|
|
999
|
+
|
|
1000
|
+
if (partPatternMatch) {
|
|
1001
|
+
continue
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
const fileSaver = getFileSaver(outputFilename, allowOverwrite)
|
|
1005
|
+
|
|
1006
|
+
await fileSaver(getEmptyRawAudio(1, 16000), translationTimeline, translationText, options.subtitles)
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
logger.end()
|
|
1010
|
+
|
|
1011
|
+
if (cliOptions.play && rawAudio) {
|
|
1012
|
+
const normalizedAudioToPlay = normalizeAudioLevel(rawAudio)
|
|
1013
|
+
|
|
1014
|
+
let transcriptToPlay: string
|
|
1015
|
+
let timelineToPlay: Timeline
|
|
1016
|
+
|
|
1017
|
+
transcriptToPlay = translationText
|
|
1018
|
+
timelineToPlay = translationWordTimeline
|
|
1019
|
+
|
|
1020
|
+
await playAudioWithWordTimeline(normalizedAudioToPlay, timelineToPlay, transcriptToPlay)
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
export async function translateText(operationData: CLIOperationData) {
|
|
1025
|
+
const logger = new Logger()
|
|
1026
|
+
|
|
1027
|
+
const { operationArgs, operationOptionsLookup, cliOptions } = operationData
|
|
1028
|
+
|
|
1029
|
+
const inputFilename = operationArgs[0]
|
|
1030
|
+
const outputFilenames = operationArgs.slice(1)
|
|
1031
|
+
|
|
1032
|
+
if (inputFilename == undefined) {
|
|
1033
|
+
throw new Error(`translate-text requires an argument containing the input file path.`)
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
if (!existsSync(inputFilename)) {
|
|
1037
|
+
throw new Error(`The given input file '${inputFilename}' was not found.`)
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
const inputFileExtension = getLowercaseFileExtension(inputFilename)
|
|
1041
|
+
const inputFileContent = await readFile(inputFilename, { encoding: 'utf-8' })
|
|
1042
|
+
|
|
1043
|
+
let inputText: string
|
|
1044
|
+
|
|
1045
|
+
if (inputFileExtension === 'txt') {
|
|
1046
|
+
inputText = inputFileContent
|
|
1047
|
+
} else if (inputFileExtension === 'html' || inputFileExtension === 'htm') {
|
|
1048
|
+
inputText = await convertHtmlToText(inputFileContent)
|
|
1049
|
+
} else if (inputFileExtension == 'srt' || inputFileExtension == 'vtt') {
|
|
1050
|
+
inputText = subtitlesToText(inputFileContent)
|
|
1051
|
+
} else {
|
|
1052
|
+
throw new Error(`align only supports reference files with extensions 'txt', 'html', 'htm', 'srt' or 'vtt'`)
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
const options = await optionsLookupToTypedObject(operationOptionsLookup, 'TextTranslationOptions')
|
|
1056
|
+
|
|
1057
|
+
const allowOverwrite = getWithDefault(cliOptions.overwrite, overwriteByDefault)
|
|
1058
|
+
|
|
1059
|
+
await checkOutputFilenames(outputFilenames, false, true, true)
|
|
1060
|
+
|
|
1061
|
+
const {
|
|
1062
|
+
text,
|
|
1063
|
+
translatedText,
|
|
1064
|
+
|
|
1065
|
+
translationPairs,
|
|
1066
|
+
|
|
1067
|
+
sourceLanguage,
|
|
1068
|
+
targetLanguage,
|
|
1069
|
+
} = await API.translateText(inputFileContent, options)
|
|
1070
|
+
|
|
1071
|
+
if (outputFilenames.length > 0) {
|
|
1072
|
+
logger.start('\nWrite output files')
|
|
1073
|
+
|
|
1074
|
+
for (const outputFilename of outputFilenames) {
|
|
1075
|
+
const partPatternMatch = outputFilename.match(filenamePlaceholderPattern)
|
|
1076
|
+
|
|
1077
|
+
if (partPatternMatch) {
|
|
1078
|
+
continue
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
const fileSaver = getFileSaver(outputFilename, allowOverwrite)
|
|
1082
|
+
|
|
1083
|
+
await fileSaver(getEmptyRawAudio(1, 16000), translationPairs as any as Timeline, translatedText, undefined)
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
logger.end()
|
|
1087
|
+
} else {
|
|
1088
|
+
logger.log(``)
|
|
1089
|
+
logger.log(translatedText)
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
export async function translateSpeech(operationData: CLIOperationData) {
|
|
776
1094
|
const logger = new Logger()
|
|
777
1095
|
|
|
778
1096
|
const { operationArgs, operationOptionsLookup, cliOptions } = operationData
|
|
@@ -798,7 +1116,19 @@ async function translateSpeech(operationData: CLIOperationData) {
|
|
|
798
1116
|
|
|
799
1117
|
await checkOutputFilenames(outputFilenames, true, true, true)
|
|
800
1118
|
|
|
801
|
-
const {
|
|
1119
|
+
const {
|
|
1120
|
+
transcript,
|
|
1121
|
+
|
|
1122
|
+
timeline,
|
|
1123
|
+
wordTimeline,
|
|
1124
|
+
|
|
1125
|
+
sourceLanguage,
|
|
1126
|
+
targetLanguage,
|
|
1127
|
+
|
|
1128
|
+
inputRawAudio,
|
|
1129
|
+
isolatedRawAudio,
|
|
1130
|
+
backgroundRawAudio
|
|
1131
|
+
} = await API.translateSpeech(inputFilename, options)
|
|
802
1132
|
|
|
803
1133
|
if (outputFilenames.length > 0) {
|
|
804
1134
|
logger.start('\nWrite output files')
|
|
@@ -859,7 +1189,7 @@ async function translateSpeech(operationData: CLIOperationData) {
|
|
|
859
1189
|
}
|
|
860
1190
|
}
|
|
861
1191
|
|
|
862
|
-
async function detectLanguage(operationData: CLIOperationData, mode: 'speech' | 'text' | 'auto') {
|
|
1192
|
+
export async function detectLanguage(operationData: CLIOperationData, mode: 'speech' | 'text' | 'auto') {
|
|
863
1193
|
const logger = new Logger()
|
|
864
1194
|
|
|
865
1195
|
const { operationArgs, operationOptionsLookup, cliOptions } = operationData
|
|
@@ -936,7 +1266,7 @@ async function detectLanguage(operationData: CLIOperationData, mode: 'speech' |
|
|
|
936
1266
|
logger.end()
|
|
937
1267
|
}
|
|
938
1268
|
|
|
939
|
-
async function detectVoiceActivity(operationData: CLIOperationData) {
|
|
1269
|
+
export async function detectVoiceActivity(operationData: CLIOperationData) {
|
|
940
1270
|
const logger = new Logger()
|
|
941
1271
|
|
|
942
1272
|
const { operationArgs, operationOptionsLookup, cliOptions } = operationData
|
|
@@ -1005,7 +1335,7 @@ async function detectVoiceActivity(operationData: CLIOperationData) {
|
|
|
1005
1335
|
}
|
|
1006
1336
|
}
|
|
1007
1337
|
|
|
1008
|
-
async function denoise(operationData: CLIOperationData) {
|
|
1338
|
+
export async function denoise(operationData: CLIOperationData) {
|
|
1009
1339
|
const logger = new Logger()
|
|
1010
1340
|
|
|
1011
1341
|
const { operationArgs, operationOptionsLookup, cliOptions } = operationData
|
|
@@ -1050,7 +1380,7 @@ async function denoise(operationData: CLIOperationData) {
|
|
|
1050
1380
|
}
|
|
1051
1381
|
}
|
|
1052
1382
|
|
|
1053
|
-
async function isolate(operationData: CLIOperationData) {
|
|
1383
|
+
export async function isolate(operationData: CLIOperationData) {
|
|
1054
1384
|
const logger = new Logger()
|
|
1055
1385
|
|
|
1056
1386
|
const { operationArgs, operationOptionsLookup, cliOptions } = operationData
|
|
@@ -1093,7 +1423,7 @@ async function isolate(operationData: CLIOperationData) {
|
|
|
1093
1423
|
}
|
|
1094
1424
|
}
|
|
1095
1425
|
|
|
1096
|
-
async function listEngines(operationData: CLIOperationData) {
|
|
1426
|
+
export async function listEngines(operationData: CLIOperationData) {
|
|
1097
1427
|
const logger = new Logger()
|
|
1098
1428
|
|
|
1099
1429
|
const { operationArgs } = operationData
|
|
@@ -1140,6 +1470,12 @@ async function listEngines(operationData: CLIOperationData) {
|
|
|
1140
1470
|
break
|
|
1141
1471
|
}
|
|
1142
1472
|
|
|
1473
|
+
case 'translate-text': {
|
|
1474
|
+
engines = API.textTranslationEngines
|
|
1475
|
+
|
|
1476
|
+
break
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1143
1479
|
case 'translate-speech': {
|
|
1144
1480
|
engines = API.speechTranslationEngines
|
|
1145
1481
|
|
|
@@ -1190,7 +1526,7 @@ async function listEngines(operationData: CLIOperationData) {
|
|
|
1190
1526
|
}
|
|
1191
1527
|
|
|
1192
1528
|
default: {
|
|
1193
|
-
throw new Error(`Unrecognized operation: '${targetOperation}'`)
|
|
1529
|
+
throw new Error(`Unrecognized operation name: '${targetOperation}'`)
|
|
1194
1530
|
}
|
|
1195
1531
|
}
|
|
1196
1532
|
|
|
@@ -1206,7 +1542,7 @@ async function listEngines(operationData: CLIOperationData) {
|
|
|
1206
1542
|
}
|
|
1207
1543
|
}
|
|
1208
1544
|
|
|
1209
|
-
async function listTTSVoices(operationData: CLIOperationData) {
|
|
1545
|
+
export async function listTTSVoices(operationData: CLIOperationData) {
|
|
1210
1546
|
const logger = new Logger()
|
|
1211
1547
|
|
|
1212
1548
|
const { operationArgs, operationOptionsLookup, cliOptions } = operationData
|
|
@@ -1268,7 +1604,7 @@ async function listTTSVoices(operationData: CLIOperationData) {
|
|
|
1268
1604
|
logger.end()
|
|
1269
1605
|
}
|
|
1270
1606
|
|
|
1271
|
-
async function installPackages(operationData: CLIOperationData) {
|
|
1607
|
+
export async function installPackages(operationData: CLIOperationData) {
|
|
1272
1608
|
const logger = new Logger()
|
|
1273
1609
|
|
|
1274
1610
|
const { operationArgs } = operationData
|
|
@@ -1299,7 +1635,7 @@ async function installPackages(operationData: CLIOperationData) {
|
|
|
1299
1635
|
}
|
|
1300
1636
|
}
|
|
1301
1637
|
|
|
1302
|
-
async function uninstallPackages(operationData: CLIOperationData) {
|
|
1638
|
+
export async function uninstallPackages(operationData: CLIOperationData) {
|
|
1303
1639
|
const logger = new Logger()
|
|
1304
1640
|
|
|
1305
1641
|
const { operationArgs } = operationData
|
|
@@ -1326,7 +1662,7 @@ async function uninstallPackages(operationData: CLIOperationData) {
|
|
|
1326
1662
|
}
|
|
1327
1663
|
}
|
|
1328
1664
|
|
|
1329
|
-
async function listPackages(operationData: CLIOperationData) {
|
|
1665
|
+
export async function listPackages(operationData: CLIOperationData) {
|
|
1330
1666
|
const logger = new Logger()
|
|
1331
1667
|
|
|
1332
1668
|
const packagesDir = await ensureAndGetPackagesDir()
|
|
@@ -1358,7 +1694,7 @@ async function listPackages(operationData: CLIOperationData) {
|
|
|
1358
1694
|
logger.log(installedPackageNamesFormatted.join('\n'))
|
|
1359
1695
|
}
|
|
1360
1696
|
|
|
1361
|
-
async function serve(operationData: CLIOperationData) {
|
|
1697
|
+
export async function serve(operationData: CLIOperationData) {
|
|
1362
1698
|
const { operationOptionsLookup } = operationData
|
|
1363
1699
|
|
|
1364
1700
|
const options = await optionsLookupToTypedObject(operationOptionsLookup, 'ServerOptions')
|
|
@@ -1500,7 +1836,7 @@ async function optionsLookupToTypedObject<K extends keyof APIOptions>(cliOptions
|
|
|
1500
1836
|
}
|
|
1501
1837
|
|
|
1502
1838
|
let cachedOptionsSchema: any
|
|
1503
|
-
|
|
1839
|
+
async function getOptionsSchema() {
|
|
1504
1840
|
if (!cachedOptionsSchema) {
|
|
1505
1841
|
cachedOptionsSchema = await readAndParseJsonFile(resolveToModuleRootDir('data/schemas/options.json'))
|
|
1506
1842
|
}
|
|
@@ -1508,7 +1844,7 @@ export async function getOptionsSchema() {
|
|
|
1508
1844
|
return cachedOptionsSchema
|
|
1509
1845
|
}
|
|
1510
1846
|
|
|
1511
|
-
|
|
1847
|
+
async function checkOutputFilenames(outputFilenames: string[], acceptMediaOutputs: boolean, acceptMetadataOutputs: boolean, acceptSubtitleOutputs: boolean) {
|
|
1512
1848
|
const supportedFileExtensions: string[] = []
|
|
1513
1849
|
|
|
1514
1850
|
if (acceptMediaOutputs) {
|
|
@@ -1562,7 +1898,7 @@ export async function checkOutputFilenames(outputFilenames: string[], acceptMedi
|
|
|
1562
1898
|
return { includesPlaceholderPattern }
|
|
1563
1899
|
}
|
|
1564
1900
|
|
|
1565
|
-
|
|
1901
|
+
async function writeOutputFilesForSegment(outputFilenames: string[], index: number, total: number, audio: RawAudio, timeline: Timeline, text: string, language: string, allowOverwrite: boolean) {
|
|
1566
1902
|
const digitCount = Math.max((total + 1).toString().length, 2)
|
|
1567
1903
|
|
|
1568
1904
|
const segmentWords = (await splitToWords(text, language)).filter(text => wordCharacterPattern.test(text))
|
|
@@ -7,6 +7,7 @@ import { commandExists, logToStderr } from '../utilities/Utilities.js'
|
|
|
7
7
|
import path from 'node:path'
|
|
8
8
|
import { loadPackage } from '../utilities/PackageManager.js'
|
|
9
9
|
import { getGlobalOption } from '../api/GlobalOptions.js'
|
|
10
|
+
import { existsSync } from '../utilities/FileSystem.js'
|
|
10
11
|
|
|
11
12
|
const log = logToStderr
|
|
12
13
|
|
|
@@ -67,6 +68,11 @@ async function transcode_CLI(ffmpegCommand: string, input: string | Buffer, outp
|
|
|
67
68
|
|
|
68
69
|
if (Buffer.isBuffer(input)) {
|
|
69
70
|
process.stdin.end(input)
|
|
71
|
+
} else if (typeof input === 'string') {
|
|
72
|
+
if (!existsSync(input)) {
|
|
73
|
+
reject(`Audio file was not found: ${input}`)
|
|
74
|
+
return
|
|
75
|
+
}
|
|
70
76
|
}
|
|
71
77
|
|
|
72
78
|
const stdoutChunks: Buffer[] = []
|
package/src/dsp/FFT.ts
CHANGED
|
@@ -48,7 +48,7 @@ export async function stftr(samples: Float32Array, fftOrder: number, windowSize:
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
binsBufferRef.clear()
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
m._kiss_fftr(statePtr, frameBufferRef.address, binsBufferRef.address)
|
|
53
53
|
|
|
54
54
|
const bins = binsBufferRef.view.slice(0, fftOrder + 2)
|
|
@@ -229,6 +229,12 @@ export function getWindowWeights(windowType: WindowType, windowSize: number) {
|
|
|
229
229
|
//weights[i] = 0.54 - (0.46 * Math.cos(2 * Math.PI * (i / (windowSize - 1))))
|
|
230
230
|
weights[i] = 0.54 - (0.46 * Math.cos(innerFactor * i))
|
|
231
231
|
}
|
|
232
|
+
} else if (windowType == 'povey') {
|
|
233
|
+
const hannWeights = getWindowWeights('hann', windowSize)
|
|
234
|
+
|
|
235
|
+
for (let i = 0; i < windowSize; i++) {
|
|
236
|
+
weights[i] = hannWeights[i] ** 0.85
|
|
237
|
+
}
|
|
232
238
|
} else {
|
|
233
239
|
throw new Error(`Unsupported window function type: ${windowType}`)
|
|
234
240
|
}
|
|
@@ -255,4 +261,4 @@ export async function testFFT1(rawAudio: RawAudio) {
|
|
|
255
261
|
return recoveredRawAudio
|
|
256
262
|
}
|
|
257
263
|
|
|
258
|
-
export type WindowType = 'hann' | 'hamming'
|
|
264
|
+
export type WindowType = 'hann' | 'hamming' | 'povey'
|