echogarden 1.3.0 → 1.3.1
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/dist/alignment/TextAlignment.d.ts +16 -0
- package/dist/alignment/TextAlignment.js +63 -0
- package/dist/alignment/TextAlignment.js.map +1 -0
- package/dist/api/Alignment.js +6 -1
- package/dist/api/Alignment.js.map +1 -1
- package/dist/api/Denoising.js +0 -1
- package/dist/api/Denoising.js.map +1 -1
- package/dist/api/LanguageDetection.js +2 -2
- package/dist/api/LanguageDetection.js.map +1 -1
- package/dist/api/Recognition.js +3 -1
- package/dist/api/Recognition.js.map +1 -1
- package/dist/api/Synthesis.js +1 -1
- package/dist/api/Synthesis.js.map +1 -1
- package/dist/api/Translation.js +3 -1
- package/dist/api/Translation.js.map +1 -1
- package/dist/api/TranslationAlignment.js +4 -1
- package/dist/api/TranslationAlignment.js.map +1 -1
- package/dist/api/VoiceActivityDetection.js +5 -2
- package/dist/api/VoiceActivityDetection.js.map +1 -1
- package/dist/audio/AudioUtilities.d.ts +1 -1
- package/dist/audio/AudioUtilities.js +2 -2
- package/dist/audio/AudioUtilities.js.map +1 -1
- package/dist/cli/CLILauncher.js +1 -2
- package/dist/cli/CLILauncher.js.map +1 -1
- package/dist/codecs/FFMpegTranscoder.js +4 -1
- package/dist/codecs/FFMpegTranscoder.js.map +1 -1
- package/dist/codecs/WaveCodec.d.ts +1 -1
- package/dist/codecs/WaveCodec.js +13 -5
- package/dist/codecs/WaveCodec.js.map +1 -1
- package/dist/dsp/SpeexResampler.js +49 -21
- package/dist/dsp/SpeexResampler.js.map +1 -1
- package/dist/synthesis/CoquiServerTTS.js +1 -1
- package/dist/synthesis/CoquiServerTTS.js.map +1 -1
- package/dist/synthesis/VitsTTS.js +1 -1
- package/dist/synthesis/VitsTTS.js.map +1 -1
- package/dist/text-translation/NLLBTextTranslation.d.ts +1 -0
- package/dist/text-translation/NLLBTextTranslation.js +237 -0
- package/dist/text-translation/NLLBTextTranslation.js.map +1 -0
- package/dist/utilities/PackageManager.js +2 -0
- package/dist/utilities/PackageManager.js.map +1 -1
- package/docs/Development.md +1 -1
- package/docs/Server.md +1 -1
- package/docs/Tasklist.md +1 -1
- package/package.json +11 -10
- package/src/alignment/TextAlignment.ts +96 -0
- package/src/api/Alignment.ts +10 -1
- package/src/api/Denoising.ts +0 -2
- package/src/api/LanguageDetection.ts +2 -3
- package/src/api/Recognition.ts +3 -1
- package/src/api/Synthesis.ts +1 -1
- package/src/api/Translation.ts +3 -1
- package/src/api/TranslationAlignment.ts +5 -1
- package/src/api/VoiceActivityDetection.ts +7 -4
- package/src/audio/AudioUtilities.ts +2 -2
- package/src/cli/CLILauncher.ts +1 -2
- package/src/codecs/FFMpegTranscoder.ts +5 -1
- package/src/codecs/WaveCodec.ts +15 -5
- package/src/dsp/SpeexResampler.ts +62 -23
- package/src/synthesis/CoquiServerTTS.ts +1 -1
- package/src/synthesis/VitsTTS.ts +2 -2
- package/src/text-translation/NLLBTextTranslation.ts +252 -0
- package/src/utilities/PackageManager.ts +3 -0
|
@@ -20,16 +20,15 @@ export async function detectVoiceActivity(input: AudioSourceParam, options: VADO
|
|
|
20
20
|
|
|
21
21
|
const startTimestamp = logger.getTimestamp()
|
|
22
22
|
|
|
23
|
-
logger.start('Prepare for voice activity detection')
|
|
24
|
-
|
|
25
23
|
const inputRawAudio = await ensureRawAudio(input)
|
|
26
24
|
|
|
25
|
+
logger.start(`Resample audio to 16kHz mono`)
|
|
27
26
|
let sourceRawAudio = await ensureRawAudio(inputRawAudio, 16000, 1)
|
|
28
27
|
|
|
29
|
-
options = extendDeep(defaultVADOptions, options)
|
|
30
|
-
|
|
31
28
|
logger.start(`Detect voice activity with ${options.engine}`)
|
|
32
29
|
|
|
30
|
+
options = extendDeep(defaultVADOptions, options)
|
|
31
|
+
|
|
33
32
|
const activityThreshold = options.activityThreshold!
|
|
34
33
|
|
|
35
34
|
let verboseTimeline: Timeline
|
|
@@ -224,6 +223,10 @@ export function convertCroppedToUncroppedTimeline(timeline: Timeline, uncropTime
|
|
|
224
223
|
function mapUsingUncropTimeline(startTimeInCroppedAudio: number, endTimeInCroppedAudio: number, uncropTimeline: Timeline) {
|
|
225
224
|
let offsetInCroppedAudio = 0
|
|
226
225
|
|
|
226
|
+
if (endTimeInCroppedAudio < startTimeInCroppedAudio) {
|
|
227
|
+
endTimeInCroppedAudio = startTimeInCroppedAudio
|
|
228
|
+
}
|
|
229
|
+
|
|
227
230
|
let bestOverlapDuration = -1
|
|
228
231
|
let mappedStartTime = -1
|
|
229
232
|
let mappedEndTime = -1
|
|
@@ -11,8 +11,8 @@ export function encodeRawAudioToWave(rawAudio: RawAudio, bitDepth: BitDepth = 16
|
|
|
11
11
|
return encodeWave(rawAudio, bitDepth, sampleFormat, speakerPositionMask)
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
export function decodeWaveToRawAudio(waveFileBuffer: Buffer, ignoreTruncatedChunks =
|
|
15
|
-
return decodeWave(waveFileBuffer, ignoreTruncatedChunks)
|
|
14
|
+
export function decodeWaveToRawAudio(waveFileBuffer: Buffer, ignoreTruncatedChunks = true, ignoreOverflowingDataChunks = true) {
|
|
15
|
+
return decodeWave(waveFileBuffer, ignoreTruncatedChunks, ignoreOverflowingDataChunks)
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
package/src/cli/CLILauncher.ts
CHANGED
|
@@ -12,9 +12,8 @@ const scriptArgs = process.argv.slice(2)
|
|
|
12
12
|
const cliScriptPath = resolveToModuleRootDir('dist/cli/CLIStarter.js')
|
|
13
13
|
|
|
14
14
|
const args = [
|
|
15
|
-
'--no-warnings',
|
|
16
|
-
'--no-experimental-fetch',
|
|
17
15
|
'--experimental-wasi-unstable-preview1',
|
|
16
|
+
'--no-warnings',
|
|
18
17
|
cliScriptPath,
|
|
19
18
|
...scriptArgs
|
|
20
19
|
]
|
|
@@ -37,7 +37,11 @@ export async function decodeToChannels(input: string | Buffer, outSampleRate?: n
|
|
|
37
37
|
|
|
38
38
|
const waveAudio = await transcode(input, outputOptions)
|
|
39
39
|
|
|
40
|
-
const
|
|
40
|
+
const logger = new Logger()
|
|
41
|
+
|
|
42
|
+
logger.start(`Convert wave buffer to raw audio`)
|
|
43
|
+
const { rawAudio } = decodeWaveToRawAudio(waveAudio)
|
|
44
|
+
logger.end()
|
|
41
45
|
|
|
42
46
|
return rawAudio
|
|
43
47
|
}
|
package/src/codecs/WaveCodec.ts
CHANGED
|
@@ -18,18 +18,20 @@ export function encodeWave(rawAudio: RawAudio, bitDepth: BitDepth = 16, sampleFo
|
|
|
18
18
|
|
|
19
19
|
const dataSubChunkBuffer = Buffer.alloc(4 + 4 + audioDataLength)
|
|
20
20
|
dataSubChunkBuffer.write('data', 0, 'ascii')
|
|
21
|
-
|
|
21
|
+
const dataChunkLength = Math.min(audioDataLength, 4294967295) // Ensure large data chunk length is clipped to max
|
|
22
|
+
dataSubChunkBuffer.writeUint32LE(dataChunkLength, 4)
|
|
22
23
|
dataSubChunkBuffer.set(audioBuffer, 8)
|
|
23
24
|
|
|
24
25
|
const riffChunkHeaderBuffer = Buffer.alloc(12)
|
|
25
26
|
riffChunkHeaderBuffer.write('RIFF', 0, 'ascii')
|
|
26
|
-
|
|
27
|
+
const riffChunkLength = Math.min(4 + formatSubChunkBuffer.length + dataSubChunkBuffer.length, 4294967295) // Ensure large RIFF chunk length is clipped to max
|
|
28
|
+
riffChunkHeaderBuffer.writeUint32LE(riffChunkLength, 4)
|
|
27
29
|
riffChunkHeaderBuffer.write('WAVE', 8, 'ascii')
|
|
28
30
|
|
|
29
31
|
return Buffer.concat([riffChunkHeaderBuffer, formatSubChunkBuffer, dataSubChunkBuffer])
|
|
30
32
|
}
|
|
31
33
|
|
|
32
|
-
export function decodeWave(waveData: Buffer, ignoreTruncatedChunks =
|
|
34
|
+
export function decodeWave(waveData: Buffer, ignoreTruncatedChunks = true, ignoreOverflowingDataChunks = true) {
|
|
33
35
|
let readOffset = 0
|
|
34
36
|
|
|
35
37
|
const riffId = waveData.subarray(readOffset, readOffset + 4).toString('ascii')
|
|
@@ -40,7 +42,7 @@ export function decodeWave(waveData: Buffer, ignoreTruncatedChunks = false) {
|
|
|
40
42
|
|
|
41
43
|
readOffset += 4
|
|
42
44
|
|
|
43
|
-
|
|
45
|
+
let riffChunkSize = waveData.readUInt32LE(readOffset)
|
|
44
46
|
|
|
45
47
|
readOffset += 4
|
|
46
48
|
|
|
@@ -50,6 +52,10 @@ export function decodeWave(waveData: Buffer, ignoreTruncatedChunks = false) {
|
|
|
50
52
|
throw new Error('Not a valid wave file. No WAVE id found at offset 8.')
|
|
51
53
|
}
|
|
52
54
|
|
|
55
|
+
if (ignoreOverflowingDataChunks && riffChunkSize === 4294967295) {
|
|
56
|
+
riffChunkSize = waveData.length - 8
|
|
57
|
+
}
|
|
58
|
+
|
|
53
59
|
if (riffChunkSize < waveData.length - 8) {
|
|
54
60
|
throw new Error(`RIFF chunk length ${riffChunkSize} is smaller than the remaining size of the buffer (${waveData.length - 8})`)
|
|
55
61
|
}
|
|
@@ -67,7 +73,7 @@ export function decodeWave(waveData: Buffer, ignoreTruncatedChunks = false) {
|
|
|
67
73
|
const subChunkIdentifier = waveData.subarray(readOffset, readOffset + 4).toString('ascii')
|
|
68
74
|
readOffset += 4
|
|
69
75
|
|
|
70
|
-
|
|
76
|
+
let subChunkSize = waveData.readUInt32LE(readOffset)
|
|
71
77
|
readOffset += 4
|
|
72
78
|
|
|
73
79
|
if (!ignoreTruncatedChunks && subChunkSize > waveData.length - readOffset) {
|
|
@@ -81,6 +87,10 @@ export function decodeWave(waveData: Buffer, ignoreTruncatedChunks = false) {
|
|
|
81
87
|
throw new Error('A data subchunk was encountered before a format subchunk')
|
|
82
88
|
}
|
|
83
89
|
|
|
90
|
+
if (ignoreOverflowingDataChunks && subChunkSize === 4294967295) {
|
|
91
|
+
subChunkSize = waveData.length - readOffset
|
|
92
|
+
}
|
|
93
|
+
|
|
84
94
|
// If the data chunk is truncated, but truncations are ignored,
|
|
85
95
|
// it would be read up to the end of the buffer
|
|
86
96
|
dataBuffers.push(waveData.subarray(readOffset, readOffset + subChunkSize))
|
|
@@ -1,16 +1,27 @@
|
|
|
1
1
|
import { RawAudio, cloneRawAudio } from '../audio/AudioUtilities.js'
|
|
2
|
+
import { concatFloat32Arrays } from '../utilities/Utilities.js'
|
|
2
3
|
import { WasmMemoryManager } from '../utilities/WasmMemoryManager.js'
|
|
3
4
|
|
|
4
5
|
let speexResamplerInstance: any
|
|
5
6
|
|
|
6
|
-
export async function resampleAudioSpeex(rawAudio: RawAudio, outSampleRate: number, quality = 0) {
|
|
7
|
+
export async function resampleAudioSpeex(rawAudio: RawAudio, outSampleRate: number, quality = 0): Promise<RawAudio> {
|
|
7
8
|
const channelCount = rawAudio.audioChannels.length
|
|
8
9
|
const inSampleRate = rawAudio.sampleRate
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
const totalSampleCount = rawAudio.audioChannels[0].length
|
|
12
|
+
const sampleRateRatio = outSampleRate / inSampleRate
|
|
13
|
+
|
|
14
|
+
if (inSampleRate === outSampleRate) {
|
|
11
15
|
return cloneRawAudio(rawAudio)
|
|
12
16
|
}
|
|
13
17
|
|
|
18
|
+
if (totalSampleCount === 0) {
|
|
19
|
+
return {
|
|
20
|
+
...cloneRawAudio(rawAudio),
|
|
21
|
+
sampleRate: outSampleRate
|
|
22
|
+
} as RawAudio
|
|
23
|
+
}
|
|
24
|
+
|
|
14
25
|
const m = await getSpeexResamplerInstance()
|
|
15
26
|
const wasmMemory = new WasmMemoryManager(m)
|
|
16
27
|
|
|
@@ -23,48 +34,76 @@ export async function resampleAudioSpeex(rawAudio: RawAudio, outSampleRate: numb
|
|
|
23
34
|
}
|
|
24
35
|
|
|
25
36
|
const initErrRef = wasmMemory.allocInt32()
|
|
26
|
-
const
|
|
37
|
+
const resamplerStateAddress = m._speex_resampler_init(channelCount, inSampleRate, outSampleRate, quality, initErrRef.address)
|
|
27
38
|
let resultCode = initErrRef.value
|
|
28
39
|
|
|
29
40
|
if (resultCode != 0) {
|
|
30
41
|
throw new Error(`Speex resampler failed while initializing with code ${resultCode}: ${speexResultCodeToString(resultCode)}`)
|
|
31
42
|
}
|
|
32
43
|
|
|
33
|
-
const
|
|
44
|
+
const inputLatency = m._speex_resampler_get_input_latency(resamplerStateAddress)
|
|
45
|
+
const outputLatency = m._speex_resampler_get_output_latency(resamplerStateAddress)
|
|
46
|
+
|
|
47
|
+
const maxChunkSize = 2 ** 20
|
|
48
|
+
|
|
49
|
+
const inputChunkSampleCountRef = wasmMemory.allocInt32()
|
|
50
|
+
const outputChunkSampleCountRef = wasmMemory.allocInt32()
|
|
51
|
+
|
|
52
|
+
const inputChunkSamplesRef = wasmMemory.allocFloat32Array(maxChunkSize * 2)
|
|
53
|
+
const outputChunkSamplesRef = wasmMemory.allocFloat32Array(Math.floor(maxChunkSize * sampleRateRatio) * 2)
|
|
54
|
+
|
|
55
|
+
const resampledAudioChunksForChannels: Float32Array[][] = []
|
|
56
|
+
|
|
57
|
+
for (let channelIndex = 0; channelIndex < channelCount; channelIndex++) {
|
|
58
|
+
resampledAudioChunksForChannels.push([])
|
|
59
|
+
}
|
|
34
60
|
|
|
35
61
|
for (let channelIndex = 0; channelIndex < channelCount; channelIndex++) {
|
|
36
|
-
|
|
62
|
+
for (let readOffset = 0; readOffset < totalSampleCount;) {
|
|
63
|
+
const isLastChunk = readOffset + maxChunkSize >= totalSampleCount
|
|
37
64
|
|
|
38
|
-
|
|
39
|
-
|
|
65
|
+
const inputPaddingSize = isLastChunk ? inputLatency : 0
|
|
66
|
+
const maxSamplesToRead = Math.min(maxChunkSize, totalSampleCount - readOffset) + inputPaddingSize
|
|
40
67
|
|
|
41
|
-
|
|
42
|
-
const inSampleCountRef = wasmMemory.allocInt32()
|
|
43
|
-
inSampleCountRef.value = inSampleCount + inputLatency
|
|
68
|
+
const maxSamplesToWrite = outputChunkSamplesRef.length
|
|
44
69
|
|
|
45
|
-
|
|
46
|
-
inSamplesRef.view.set(channelSamples)
|
|
70
|
+
const inputChunkSamplesForChannel = rawAudio.audioChannels[channelIndex].slice(readOffset, readOffset + maxSamplesToRead)
|
|
47
71
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
outSampleCountRef.value = outSampleCount + outputLatency
|
|
72
|
+
inputChunkSampleCountRef.value = maxSamplesToRead
|
|
73
|
+
outputChunkSampleCountRef.value = maxSamplesToWrite
|
|
51
74
|
|
|
52
|
-
|
|
75
|
+
inputChunkSamplesRef.view.set(inputChunkSamplesForChannel)
|
|
76
|
+
resultCode = m._speex_resampler_process_float(resamplerStateAddress, channelIndex, inputChunkSamplesRef.address, inputChunkSampleCountRef.address, outputChunkSamplesRef.address, outputChunkSampleCountRef.address)
|
|
53
77
|
|
|
54
|
-
|
|
78
|
+
if (resultCode != 0) {
|
|
79
|
+
throw new Error(`Speex resampler failed while resampling with code ${resultCode}: ${speexResultCodeToString(resultCode)}`)
|
|
80
|
+
}
|
|
55
81
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
82
|
+
const samplesReadCount = inputChunkSampleCountRef.value
|
|
83
|
+
const samplesWrittenCount = outputChunkSampleCountRef.value
|
|
84
|
+
|
|
85
|
+
const resampledChannelAudio = outputChunkSamplesRef.view.slice(0, samplesWrittenCount)
|
|
59
86
|
|
|
60
|
-
|
|
87
|
+
resampledAudioChunksForChannels[channelIndex].push(resampledChannelAudio)
|
|
61
88
|
|
|
62
|
-
|
|
89
|
+
readOffset += samplesReadCount
|
|
90
|
+
}
|
|
63
91
|
}
|
|
64
92
|
|
|
65
|
-
m._speex_resampler_destroy(
|
|
93
|
+
m._speex_resampler_destroy(resamplerStateAddress)
|
|
66
94
|
wasmMemory.freeAll()
|
|
67
95
|
|
|
96
|
+
const resampledAudio: RawAudio = {
|
|
97
|
+
audioChannels: [],
|
|
98
|
+
sampleRate: outSampleRate
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
for (let i = 0; i < channelCount; i++) {
|
|
102
|
+
resampledAudioChunksForChannels[i][0] = resampledAudioChunksForChannels[i][0].slice(outputLatency)
|
|
103
|
+
|
|
104
|
+
resampledAudio.audioChannels.push(concatFloat32Arrays(resampledAudioChunksForChannels[i]))
|
|
105
|
+
}
|
|
106
|
+
|
|
68
107
|
return resampledAudio
|
|
69
108
|
}
|
|
70
109
|
|
|
@@ -21,7 +21,7 @@ export async function synthesize(text: string, speakerId: string | null, serverU
|
|
|
21
21
|
|
|
22
22
|
const waveData = Buffer.from(response.data)
|
|
23
23
|
|
|
24
|
-
const rawAudio = decodeWaveToRawAudio(waveData)
|
|
24
|
+
const { rawAudio } = decodeWaveToRawAudio(waveData)
|
|
25
25
|
|
|
26
26
|
logger.end()
|
|
27
27
|
|
package/src/synthesis/VitsTTS.ts
CHANGED
|
@@ -52,7 +52,7 @@ export class VitsTTS {
|
|
|
52
52
|
|
|
53
53
|
await this.initializeIfNeeded()
|
|
54
54
|
|
|
55
|
-
await logger.startAsync('Prepare for synthesis')
|
|
55
|
+
await logger.startAsync('Prepare for VITS synthesis')
|
|
56
56
|
|
|
57
57
|
const metadata = this.metadata
|
|
58
58
|
const phonemeMap = this.phonemeMap!
|
|
@@ -78,7 +78,7 @@ export class VitsTTS {
|
|
|
78
78
|
voice: espeakVoice,
|
|
79
79
|
useKlatt: false
|
|
80
80
|
}
|
|
81
|
-
|
|
81
|
+
|
|
82
82
|
const { referenceSynthesizedAudio, referenceTimeline, fragments, phonemizedFragmentsSubstitutions, phonemizedSentence } = await Espeak.preprocessAndSynthesize(sentence, languageCode, espeakOptions, lexicons)
|
|
83
83
|
|
|
84
84
|
if (phonemizedSentence.length == 0) {
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { Logger } from '../utilities/Logger.js'
|
|
2
|
+
import { loadPackage } from '../utilities/PackageManager.js'
|
|
3
|
+
|
|
4
|
+
export async function translateText(sourceText: string, sourceLanguage: string, targetLanguage: string) {
|
|
5
|
+
const logger = new Logger()
|
|
6
|
+
|
|
7
|
+
const { AutoTokenizer, M2M100ForConditionalGeneration } = await import('@echogarden/transformers-nodejs-lite')
|
|
8
|
+
|
|
9
|
+
const modelPath = await loadPackage(`xenova-nllb-200-distilled-600M-quantized`)
|
|
10
|
+
|
|
11
|
+
const tokenizer = await AutoTokenizer.from_pretrained(modelPath)
|
|
12
|
+
const model = await M2M100ForConditionalGeneration.from_pretrained(modelPath)
|
|
13
|
+
|
|
14
|
+
const config = {
|
|
15
|
+
src_lang: 'eng_Latn',
|
|
16
|
+
tgt_lang: 'fra_Latn'
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const inputs = (tokenizer as any)._build_translation_inputs(sourceText, {
|
|
20
|
+
padding: true,
|
|
21
|
+
truncation: true,
|
|
22
|
+
}, config)
|
|
23
|
+
|
|
24
|
+
const result = await model.generate(inputs.input_ids, config)
|
|
25
|
+
|
|
26
|
+
logger.log(tokenizer.model.convert_ids_to_tokens(result[0]))
|
|
27
|
+
|
|
28
|
+
const inputTokens = tokenizer.model.convert_ids_to_tokens(Array.from(inputs.input_ids.data))
|
|
29
|
+
const embeddingResult = await model(inputs)
|
|
30
|
+
|
|
31
|
+
const lastHiddenState = embeddingResult.last_hidden_state
|
|
32
|
+
|
|
33
|
+
const tokenCount = lastHiddenState.dims[1]
|
|
34
|
+
const embeddingSize = lastHiddenState.dims[2]
|
|
35
|
+
|
|
36
|
+
for (let i = 0; i < tokenCount; i++) {
|
|
37
|
+
const tokenEmbedding = lastHiddenState.data.slice(i * embeddingSize, (i + 1) * embeddingSize)
|
|
38
|
+
|
|
39
|
+
const tokenId = inputTokens[i]
|
|
40
|
+
|
|
41
|
+
logger.log(`Token ${i} (${tokenId}):`, tokenEmbedding);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
logger.log(inputTokens)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const languageNameToNLLBCode: Record<string, string> = {
|
|
48
|
+
'Acehnese (Arabic script)': 'ace_Arab',
|
|
49
|
+
'Acehnese (Latin script)': 'ace_Latn',
|
|
50
|
+
'Afrikaans': 'afr_Latn',
|
|
51
|
+
'Akan': 'aka_Latn',
|
|
52
|
+
'Amharic': 'amh_Ethi',
|
|
53
|
+
'Armenian': 'hye_Armn',
|
|
54
|
+
'Assamese': 'asm_Beng',
|
|
55
|
+
'Asturian': 'ast_Latn',
|
|
56
|
+
'Awadhi': 'awa_Deva',
|
|
57
|
+
'Ayacucho Quechua': 'quy_Latn',
|
|
58
|
+
'Balinese': 'ban_Latn',
|
|
59
|
+
'Bambara': 'bam_Latn',
|
|
60
|
+
'Banjar (Arabic script)': 'bjn_Arab',
|
|
61
|
+
'Banjar (Latin script)': 'bjn_Latn',
|
|
62
|
+
'Bashkir': 'bak_Cyrl',
|
|
63
|
+
'Basque': 'eus_Latn',
|
|
64
|
+
'Belarusian': 'bel_Cyrl',
|
|
65
|
+
'Bemba': 'bem_Latn',
|
|
66
|
+
'Bengali': 'ben_Beng',
|
|
67
|
+
'Bhojpuri': 'bho_Deva',
|
|
68
|
+
'Bosnian': 'bos_Latn',
|
|
69
|
+
'Buginese': 'bug_Latn',
|
|
70
|
+
'Bulgarian': 'bul_Cyrl',
|
|
71
|
+
'Burmese': 'mya_Mymr',
|
|
72
|
+
'Catalan': 'cat_Latn',
|
|
73
|
+
'Cebuano': 'ceb_Latn',
|
|
74
|
+
'Central Atlas Tamazight': 'tzm_Tfng',
|
|
75
|
+
'Central Aymara': 'ayr_Latn',
|
|
76
|
+
'Central Kanuri (Arabic script)': 'knc_Arab',
|
|
77
|
+
'Central Kanuri (Latin script)': 'knc_Latn',
|
|
78
|
+
'Central Kurdish': 'ckb_Arab',
|
|
79
|
+
'Chhattisgarhi': 'hne_Deva',
|
|
80
|
+
'Chinese (Simplified)': 'zho_Hans',
|
|
81
|
+
'Chinese (Traditional)': 'zho_Hant',
|
|
82
|
+
'Chokwe': 'cjk_Latn',
|
|
83
|
+
'Crimean Tatar': 'crh_Latn',
|
|
84
|
+
'Croatian': 'hrv_Latn',
|
|
85
|
+
'Czech': 'ces_Latn',
|
|
86
|
+
'Danish': 'dan_Latn',
|
|
87
|
+
'Dari': 'prs_Arab',
|
|
88
|
+
'Dutch': 'nld_Latn',
|
|
89
|
+
'Dyula': 'dyu_Latn',
|
|
90
|
+
'Dzongkha': 'dzo_Tibt',
|
|
91
|
+
'Eastern Panjabi': 'pan_Guru',
|
|
92
|
+
'Eastern Yiddish': 'ydd_Hebr',
|
|
93
|
+
'Egyptian Arabic': 'arz_Arab',
|
|
94
|
+
'English': 'eng_Latn',
|
|
95
|
+
'Esperanto': 'epo_Latn',
|
|
96
|
+
'Estonian': 'est_Latn',
|
|
97
|
+
'Ewe': 'ewe_Latn',
|
|
98
|
+
'Faroese': 'fao_Latn',
|
|
99
|
+
'Fijian': 'fij_Latn',
|
|
100
|
+
'Finnish': 'fin_Latn',
|
|
101
|
+
'Fon': 'fon_Latn',
|
|
102
|
+
'French': 'fra_Latn',
|
|
103
|
+
'Friulian': 'fur_Latn',
|
|
104
|
+
'Galician': 'glg_Latn',
|
|
105
|
+
'Ganda': 'lug_Latn',
|
|
106
|
+
'Georgian': 'kat_Geor',
|
|
107
|
+
'German': 'deu_Latn',
|
|
108
|
+
'Greek': 'ell_Grek',
|
|
109
|
+
'Guarani': 'grn_Latn',
|
|
110
|
+
'Gujarati': 'guj_Gujr',
|
|
111
|
+
'Haitian Creole': 'hat_Latn',
|
|
112
|
+
'Halh Mongolian': 'khk_Cyrl',
|
|
113
|
+
'Hausa': 'hau_Latn',
|
|
114
|
+
'Hebrew': 'heb_Hebr',
|
|
115
|
+
'Hindi': 'hin_Deva',
|
|
116
|
+
'Hungarian': 'hun_Latn',
|
|
117
|
+
'Icelandic': 'isl_Latn',
|
|
118
|
+
'Igbo': 'ibo_Latn',
|
|
119
|
+
'Ilocano': 'ilo_Latn',
|
|
120
|
+
'Indonesian': 'ind_Latn',
|
|
121
|
+
'Irish': 'gle_Latn',
|
|
122
|
+
'Italian': 'ita_Latn',
|
|
123
|
+
'Japanese': 'jpn_Jpan',
|
|
124
|
+
'Javanese': 'jav_Latn',
|
|
125
|
+
'Jingpho': 'kac_Latn',
|
|
126
|
+
'Kabiyè': 'kbp_Latn',
|
|
127
|
+
'Kabuverdianu': 'kea_Latn',
|
|
128
|
+
'Kabyle': 'kab_Latn',
|
|
129
|
+
'Kamba': 'kam_Latn',
|
|
130
|
+
'Kannada': 'kan_Knda',
|
|
131
|
+
'Kashmiri (Arabic script)': 'kas_Arab',
|
|
132
|
+
'Kashmiri (Devanagari script)': 'kas_Deva',
|
|
133
|
+
'Kazakh': 'kaz_Cyrl',
|
|
134
|
+
'Khmer': 'khm_Khmr',
|
|
135
|
+
'Kikongo': 'kon_Latn',
|
|
136
|
+
'Kikuyu': 'kik_Latn',
|
|
137
|
+
'Kimbundu': 'kmb_Latn',
|
|
138
|
+
'Kinyarwanda': 'kin_Latn',
|
|
139
|
+
'Korean': 'kor_Hang',
|
|
140
|
+
'Kyrgyz': 'kir_Cyrl',
|
|
141
|
+
'Lao': 'lao_Laoo',
|
|
142
|
+
'Latgalian': 'ltg_Latn',
|
|
143
|
+
'Ligurian': 'lij_Latn',
|
|
144
|
+
'Limburgish': 'lim_Latn',
|
|
145
|
+
'Lingala': 'lin_Latn',
|
|
146
|
+
'Lithuanian': 'lit_Latn',
|
|
147
|
+
'Lombard': 'lmo_Latn',
|
|
148
|
+
'Luba-Kasai': 'lua_Latn',
|
|
149
|
+
'Luo': 'luo_Latn',
|
|
150
|
+
'Luxembourgish': 'ltz_Latn',
|
|
151
|
+
'Macedonian': 'mkd_Cyrl',
|
|
152
|
+
'Magahi': 'mag_Deva',
|
|
153
|
+
'Maithili': 'mai_Deva',
|
|
154
|
+
'Malayalam': 'mal_Mlym',
|
|
155
|
+
'Maltese': 'mlt_Latn',
|
|
156
|
+
'Maori': 'mri_Latn',
|
|
157
|
+
'Marathi': 'mar_Deva',
|
|
158
|
+
'Meitei (Bengali script)': 'mni_Beng',
|
|
159
|
+
'Mesopotamian Arabic': 'acm_Arab',
|
|
160
|
+
'Minangkabau (Arabic script)': 'min_Arab',
|
|
161
|
+
'Minangkabau (Latin script)': 'min_Latn',
|
|
162
|
+
'Mizo': 'lus_Latn',
|
|
163
|
+
'Modern Standard Arabic (Romanized)': 'arb_Latn',
|
|
164
|
+
'Modern Standard Arabic': 'arb_Arab',
|
|
165
|
+
'Moroccan Arabic': 'ary_Arab',
|
|
166
|
+
'Mossi': 'mos_Latn',
|
|
167
|
+
'Najdi Arabic': 'ars_Arab',
|
|
168
|
+
'Nepali': 'npi_Deva',
|
|
169
|
+
'Nigerian Fulfulde': 'fuv_Latn',
|
|
170
|
+
'North Azerbaijani': 'azj_Latn',
|
|
171
|
+
'North Levantine Arabic': 'apc_Arab',
|
|
172
|
+
'Northern Kurdish': 'kmr_Latn',
|
|
173
|
+
'Northern Sotho': 'nso_Latn',
|
|
174
|
+
'Northern Uzbek': 'uzn_Latn',
|
|
175
|
+
'Norwegian Bokmål': 'nob_Latn',
|
|
176
|
+
'Norwegian Nynorsk': 'nno_Latn',
|
|
177
|
+
'Nuer': 'nus_Latn',
|
|
178
|
+
'Nyanja': 'nya_Latn',
|
|
179
|
+
'Occitan': 'oci_Latn',
|
|
180
|
+
'Odia': 'ory_Orya',
|
|
181
|
+
'Pangasinan': 'pag_Latn',
|
|
182
|
+
'Papiamento': 'pap_Latn',
|
|
183
|
+
'Plateau Malagasy': 'plt_Latn',
|
|
184
|
+
'Polish': 'pol_Latn',
|
|
185
|
+
'Portuguese': 'por_Latn',
|
|
186
|
+
'Romanian': 'ron_Latn',
|
|
187
|
+
'Rundi': 'run_Latn',
|
|
188
|
+
'Russian': 'rus_Cyrl',
|
|
189
|
+
'Samoan': 'smo_Latn',
|
|
190
|
+
'Sango': 'sag_Latn',
|
|
191
|
+
'Sanskrit': 'san_Deva',
|
|
192
|
+
'Santali': 'sat_Olck',
|
|
193
|
+
'Sardinian': 'srd_Latn',
|
|
194
|
+
'Scottish Gaelic': 'gla_Latn',
|
|
195
|
+
'Serbian': 'srp_Cyrl',
|
|
196
|
+
'Shan': 'shn_Mymr',
|
|
197
|
+
'Shona': 'sna_Latn',
|
|
198
|
+
'Sicilian': 'scn_Latn',
|
|
199
|
+
'Silesian': 'szl_Latn',
|
|
200
|
+
'Sindhi': 'snd_Arab',
|
|
201
|
+
'Sinhala': 'sin_Sinh',
|
|
202
|
+
'Slovak': 'slk_Latn',
|
|
203
|
+
'Slovenian': 'slv_Latn',
|
|
204
|
+
'Somali': 'som_Latn',
|
|
205
|
+
'South Azerbaijani': 'azb_Arab',
|
|
206
|
+
'South Levantine Arabic': 'ajp_Arab',
|
|
207
|
+
'Southern Pashto': 'pbt_Arab',
|
|
208
|
+
'Southern Sotho': 'sot_Latn',
|
|
209
|
+
'Southwestern Dinka': 'dik_Latn',
|
|
210
|
+
'Spanish': 'spa_Latn',
|
|
211
|
+
'Standard Latvian': 'lvs_Latn',
|
|
212
|
+
'Standard Malay': 'zsm_Latn',
|
|
213
|
+
'Standard Tibetan': 'bod_Tibt',
|
|
214
|
+
'Sundanese': 'sun_Latn',
|
|
215
|
+
'Swahili': 'swh_Latn',
|
|
216
|
+
'Swati': 'ssw_Latn',
|
|
217
|
+
'Swedish': 'swe_Latn',
|
|
218
|
+
'Tagalog': 'tgl_Latn',
|
|
219
|
+
'Tajik': 'tgk_Cyrl',
|
|
220
|
+
'Tamasheq (Latin script)': 'taq_Latn',
|
|
221
|
+
'Tamasheq (Tifinagh script)': 'taq_Tfng',
|
|
222
|
+
'Tamil': 'tam_Taml',
|
|
223
|
+
'Tatar': 'tat_Cyrl',
|
|
224
|
+
'Ta’izzi-Adeni Arabic': 'acq_Arab',
|
|
225
|
+
'Telugu': 'tel_Telu',
|
|
226
|
+
'Thai': 'tha_Thai',
|
|
227
|
+
'Tigrinya': 'tir_Ethi',
|
|
228
|
+
'Tok Pisin': 'tpi_Latn',
|
|
229
|
+
'Tosk Albanian': 'als_Latn',
|
|
230
|
+
'Tsonga': 'tso_Latn',
|
|
231
|
+
'Tswana': 'tsn_Latn',
|
|
232
|
+
'Tumbuka': 'tum_Latn',
|
|
233
|
+
'Tunisian Arabic': 'aeb_Arab',
|
|
234
|
+
'Turkish': 'tur_Latn',
|
|
235
|
+
'Turkmen': 'tuk_Latn',
|
|
236
|
+
'Twi': 'twi_Latn',
|
|
237
|
+
'Ukrainian': 'ukr_Cyrl',
|
|
238
|
+
'Umbundu': 'umb_Latn',
|
|
239
|
+
'Urdu': 'urd_Arab',
|
|
240
|
+
'Uyghur': 'uig_Arab',
|
|
241
|
+
'Venetian': 'vec_Latn',
|
|
242
|
+
'Vietnamese': 'vie_Latn',
|
|
243
|
+
'Waray': 'war_Latn',
|
|
244
|
+
'Welsh': 'cym_Latn',
|
|
245
|
+
'West Central Oromo': 'gaz_Latn',
|
|
246
|
+
'Western Persian': 'pes_Arab',
|
|
247
|
+
'Wolof': 'wol_Latn',
|
|
248
|
+
'Xhosa': 'xho_Latn',
|
|
249
|
+
'Yoruba': 'yor_Latn',
|
|
250
|
+
'Yue Chinese': 'yue_Hant',
|
|
251
|
+
'Zulu': 'zul_Latn',
|
|
252
|
+
}
|
|
@@ -182,4 +182,7 @@ const packageVersionTagResolutionLookup: { [packageName: string]: string } = {
|
|
|
182
182
|
|
|
183
183
|
'whisper.cpp-binaries-windows-x64-cublas-12.4.0-latest-patched': '20240409',
|
|
184
184
|
'whisper.cpp-binaries-windows-x64-cublas-11.8.0-latest-patched': '20240409',
|
|
185
|
+
|
|
186
|
+
'xenova-multilingual-e5-small-quantized': '20240504',
|
|
187
|
+
'xenova-nllb-200-distilled-600M-quantized': '20240505',
|
|
185
188
|
}
|