echogarden 0.11.22 → 0.12.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.
@@ -1,7 +1,7 @@
1
- import path from "node:path";
2
- import { downloadAndExtractTarball } from "./FileDownloader.js";
3
- import { getAppDataDir, getAppTempDir, ensureDir, existsSync, remove } from "./FileSystem.js";
4
- import { appName } from "../api/Common.js";
1
+ import path from 'node:path';
2
+ import { downloadAndExtractTarball } from './FileDownloader.js';
3
+ import { getAppDataDir, getAppTempDir, ensureDir, existsSync, remove } from './FileSystem.js';
4
+ import { appName } from '../api/Common.js';
5
5
  export async function loadPackage(packageName) {
6
6
  packageName = resolveToVersionedPackageNameIfNeeded(packageName);
7
7
  const packagesPath = await ensureAndGetPackagesDir();
@@ -26,7 +26,7 @@ export async function removePackage(packageName) {
26
26
  }
27
27
  export async function ensureAndGetPackagesDir() {
28
28
  const dataPath = getAppDataDir(appName);
29
- const packagesPath = path.join(dataPath, "packages");
29
+ const packagesPath = path.join(dataPath, 'packages');
30
30
  await ensureDir(packagesPath);
31
31
  return packagesPath;
32
32
  }
@@ -44,39 +44,61 @@ export function getVersionTagFromPackageName(packageName) {
44
44
  export function resolveVersionTagForUnversionedPackageName(unversionedPackageName) {
45
45
  return packageVersionTagResolutionLookup[unversionedPackageName] || defaultVersionTag;
46
46
  }
47
- const basePackageUrl = "https://huggingface.co/echogarden/echogarden-packages/resolve/main/";
48
- const defaultVersionTag = "20230718";
47
+ const basePackageUrl = 'https://huggingface.co/echogarden/echogarden-packages/resolve/main/';
48
+ const defaultVersionTag = '20230718';
49
49
  const packageVersionTagResolutionLookup = {
50
- "sox-14.4.2-linux-minimal": "20230802",
51
- "vits-de_DE-thorsten_emotional-medium": "20230808",
52
- "vits-en_GB-semaine-medium": "20230808",
53
- "vits-fr_FR-upmc-medium": "20230808",
54
- "vits-lb_LU-marylux-medium": "20230808",
55
- "vits-ro_RO-mihai-medium": "20230808",
56
- "vits-sr_RS-serbski_institut-medium": "20230808",
57
- "vits-tr_TR-dfki-medium": "20230808",
58
- "vits-cs_CZ-jirka-medium": "20230824",
59
- "vits-de_DE-thorsten-high": "20230824",
60
- "vits-hu_HU-anna-medium": "20230824",
61
- "vits-pt_PT-tugao-medium": "20230824",
62
- "vits-sk_SK-lili-medium": "20230824",
63
- "vits-tr_TR-fahrettin-medium": "20230824",
64
- "vits-ar_JO-kareem-medium": "20231022",
65
- "vits-cs_CZ-jirka-low": "20231022",
66
- "vits-en_US-hfc_male-medium": "20231022",
67
- "vits-en_US-libritts_r-medium": "20231022",
68
- "vits-hu_HU-imre-medium": "20231022",
69
- "vits-pl_PL-mc_speech-medium": "20231022",
70
- "whisper-tiny": "20231126",
71
- "whisper-tiny.en": "20231126",
72
- "whisper-base": "20231126",
73
- "whisper-base.en": "20231126",
74
- "whisper-small": "20231126",
75
- "whisper-small.en": "20231126",
76
- "whisper-medium": "20231126",
77
- "whisper-medium.en": "20231126",
78
- "whisper-large-v3": "20231126",
79
- "vits-ar_JO-kareem-low": "20231126",
80
- "vits-en_US-hfc_female-medium": "20231126",
50
+ 'sox-14.4.2-linux-minimal': '20230802',
51
+ 'vits-de_DE-thorsten_emotional-medium': '20230808',
52
+ 'vits-en_GB-semaine-medium': '20230808',
53
+ 'vits-fr_FR-upmc-medium': '20230808',
54
+ 'vits-lb_LU-marylux-medium': '20230808',
55
+ 'vits-ro_RO-mihai-medium': '20230808',
56
+ 'vits-sr_RS-serbski_institut-medium': '20230808',
57
+ 'vits-tr_TR-dfki-medium': '20230808',
58
+ 'vits-cs_CZ-jirka-medium': '20230824',
59
+ 'vits-de_DE-thorsten-high': '20230824',
60
+ 'vits-hu_HU-anna-medium': '20230824',
61
+ 'vits-pt_PT-tugao-medium': '20230824',
62
+ 'vits-sk_SK-lili-medium': '20230824',
63
+ 'vits-tr_TR-fahrettin-medium': '20230824',
64
+ 'vits-ar_JO-kareem-medium': '20231022',
65
+ 'vits-cs_CZ-jirka-low': '20231022',
66
+ 'vits-en_US-hfc_male-medium': '20231022',
67
+ 'vits-en_US-libritts_r-medium': '20231022',
68
+ 'vits-hu_HU-imre-medium': '20231022',
69
+ 'vits-pl_PL-mc_speech-medium': '20231022',
70
+ 'whisper-tiny': '20231126',
71
+ 'whisper-tiny.en': '20231126',
72
+ 'whisper-base': '20231126',
73
+ 'whisper-base.en': '20231126',
74
+ 'whisper-small': '20231126',
75
+ 'whisper-small.en': '20231126',
76
+ 'whisper-medium': '20231126',
77
+ 'whisper-medium.en': '20231126',
78
+ 'whisper-large-v3': '20231126',
79
+ 'vits-ar_JO-kareem-low': '20231126',
80
+ 'vits-en_US-hfc_female-medium': '20231126',
81
+ 'ffmpeg-6.0-win32-x64': '20240316',
82
+ 'ffmpeg-6.0-win32-ia32': '20240316',
83
+ 'ffmpeg-6.0-darwin-x64': '20240316',
84
+ 'ffmpeg-6.0-darwin-arm64': '20240316',
85
+ 'ffmpeg-6.0-linux-x64': '20240316',
86
+ 'ffmpeg-6.0-linux-ia32': '20240316',
87
+ 'ffmpeg-6.0-linux-arm64': '20240316',
88
+ 'ffmpeg-6.0-linux-arm': '20240316',
89
+ 'ffmpeg-6.0-freebsd-x64': '20240316',
90
+ 'vits-de_DE-mls-medium': '20240316',
91
+ 'vits-en_GB-cori-high': '20240316',
92
+ 'vits-en_US-kristin-medium': '20240316',
93
+ 'vits-en_US-ljspeech-high': '20240316',
94
+ 'vits-en_US-ljspeech-medium': '20240316',
95
+ 'vits-es_MX-claude-high': '20240316',
96
+ 'vits-fa_IR-amir-medium': '20240316',
97
+ 'vits-fa_IR-gyro-medium': '20240316',
98
+ 'vits-fr_FR-mls-medium': '20240316',
99
+ 'vits-fr_FR-tom-medium': '20240316',
100
+ 'vits-nl_NL-mls-medium': '20240316',
101
+ 'vits-sl_SI-artur-medium': '20240316',
102
+ 'vits-tr_TR-fettah-medium': '20240316',
81
103
  };
82
104
  //# sourceMappingURL=PackageManager.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PackageManager.js","sourceRoot":"","sources":["../../src/utilities/PackageManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PackageManager.js","sourceRoot":"","sources":["../../src/utilities/PackageManager.ts"],"names":[],"mappings":"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"}
package/docs/API.md CHANGED
@@ -248,6 +248,31 @@ Converts subtitles to a timeline.
248
248
 
249
249
  Timeline object.
250
250
 
251
+ ## Global options
252
+
253
+ ### `setGlobalOption(key, value)`
254
+
255
+ Set a global option.
256
+
257
+ Supported keys:
258
+
259
+ * `'ffmpegPath'`: override FFMpeg executable path
260
+ * `'soxPath'`: override SoX executable path
261
+
262
+ ### `getGlobalOption(key)`
263
+
264
+ Get a global option.
265
+
266
+ Supported keys:
267
+
268
+ * `'ffmpegPath'`: get FFMpeg executable path
269
+ * `'soxPath'`: get SoX executable path
270
+
271
+ #### Returns:
272
+
273
+ The value associated with the given key.
274
+
251
275
  ## TODO
252
276
 
253
277
  Expose more methods that may be useful for developers, like phonemization, etc.
278
+
package/docs/Engines.md CHANGED
@@ -4,7 +4,7 @@
4
4
  ## Text to speech
5
5
 
6
6
  **Offline**:
7
- * [VITS](https://github.com/jaywalnut310/vits) (`vits`): a high-quality end-to-end neural speech synthesis architecture. Available models were trained by Michael Hansen as part of his [Piper speech synthesis system](https://github.com/rhasspy/piper). Currently there are 104 voices, in a range of languages, including English (US, UK), Spanish (ES, MX), Portuguese (PT, BR), Italian, French, German, Dutch (NL, BE), Swedish, Norwegian, Danish, Finnish, Polish, Greek, Romanian, Serbian, Czech, Hungarian, Slovak, Turkish, Arabic, Russian, Ukrainian, Catalan, Luxemburgish, Icelandic, Swahili, Kazakh, Georgian, Nepali, Vietnamese and Chinese. You can listen to audio samples of all voices and languages in [Piper's samples page](https://rhasspy.github.io/piper-samples/).
7
+ * [VITS](https://github.com/jaywalnut310/vits) (`vits`): a high-quality end-to-end neural speech synthesis architecture. Available models were trained by Michael Hansen as part of his [Piper speech synthesis system](https://github.com/rhasspy/piper). Currently there are 117 voices, in a range of languages, including English (US, UK), Spanish (ES, MX), Portuguese (PT, BR), Italian, French, German, Dutch (NL, BE), Swedish, Norwegian, Danish, Finnish, Polish, Greek, Romanian, Serbian, Czech, Hungarian, Slovak, Slovenian, Turkish, Arabic, Farsi, Russian, Ukrainian, Catalan, Luxemburgish, Icelandic, Swahili, Kazakh, Georgian, Nepali, Vietnamese and Chinese. You can listen to audio samples of all voices and languages in [Piper's samples page](https://rhasspy.github.io/piper-samples/).
8
8
  * [SVOX Pico](https://github.com/naggety/picotts) (`pico`): a legacy diphone-based synthesis engine. Supports English (US, UK), Spanish, Italian, French, and German.
9
9
  * [Flite](https://github.com/festvox/flite) (`flite`): a legacy diphone-based synthesis engine. Supports English (US, Scottish), and several Indic languages: Hindi, Bengali, Marathi, Telugu, Tamil, Gujarati, Kannada and Punjabi.
10
10
  * [eSpeak-NG](https://github.com/espeak-ng/espeak-ng/) (`espeak`): a lightweight "robot" sounding formant-based synthesizer. Supports 100+ languages. Extensively used internally for speech alignment, phonemization, and other internal tasks.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "echogarden",
3
- "version": "0.11.22",
3
+ "version": "0.12.0",
4
4
  "description": "An integrated speech toolset, providing a variety of synthesis, recognition, alignment, and other processing tools, designed to be directly accessible to end-users.",
5
5
  "author": "Rotem Dan",
6
6
  "license": "GPL-3.0",
@@ -54,8 +54,8 @@
54
54
  "echogarden": "./dist/cli/CLILauncher.js"
55
55
  },
56
56
  "dependencies": {
57
- "@aws-sdk/client-polly": "^3.529.1",
58
- "@aws-sdk/client-transcribe-streaming": "^3.529.1",
57
+ "@aws-sdk/client-polly": "^3.535.0",
58
+ "@aws-sdk/client-transcribe-streaming": "^3.535.0",
59
59
  "@echogarden/espeak-ng-emscripten": "^0.1.2",
60
60
  "@echogarden/fasttext-wasm": "^0.1.0",
61
61
  "@echogarden/flite-wasi": "^0.1.1",
@@ -121,12 +121,12 @@
121
121
  "@types/msgpack-lite": "^0.1.11",
122
122
  "@types/ndarray": "^1.0.14",
123
123
  "@types/ndarray-ops": "^1.2.7",
124
- "@types/node": "^20.11.25",
124
+ "@types/node": "^20.11.28",
125
125
  "@types/recursive-readdir": "^2.2.4",
126
126
  "@types/tar": "^6.1.11",
127
127
  "@types/ws": "^8.5.10",
128
- "@typescript-eslint/eslint-plugin": "^7.1.1",
129
- "@typescript-eslint/parser": "^7.1.1",
128
+ "@typescript-eslint/eslint-plugin": "^7.2.0",
129
+ "@typescript-eslint/parser": "^7.2.0",
130
130
  "eslint": "^8.57.0",
131
131
  "ts-json-schema-generator": "^1.5.0",
132
132
  "typescript": "^5.4.2"
package/src/api/API.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  /// <reference path="../typings/Fillers.d.ts" />
2
2
 
3
3
  export * from "./Common.js"
4
+ export * from "./GlobalOptions.js"
4
5
  export * from "./Synthesis.js"
5
6
  export * from "./Recognition.js"
6
7
  export * from "./Alignment.js"
@@ -0,0 +1,25 @@
1
+ export function getGlobalOption<K extends keyof GlobalOptions>(key: K): GlobalOptions[K] {
2
+ if (!Object.keys(globalOptions).includes(key)) {
3
+ throw new Error(`Unknown global option key '${key}'`)
4
+ }
5
+
6
+ return globalOptions[key]
7
+ }
8
+
9
+ export function setGlobalOption<K extends keyof GlobalOptions>(key: K, value: GlobalOptions[K]) {
10
+ if (!Object.keys(globalOptions).includes(key)) {
11
+ throw new Error(`Unknown global option key '${key}'`)
12
+ }
13
+
14
+ globalOptions[key] = value as any
15
+ }
16
+
17
+ export interface GlobalOptions {
18
+ ffmpegPath?: string
19
+ soxPath?: string
20
+ }
21
+
22
+ const globalOptions = {
23
+ ffmpegPath: undefined,
24
+ soxPath: undefined
25
+ }
@@ -42,12 +42,12 @@ export function trimAudioEnd(audioSamples: Float32Array, targetEndSilentSampleCo
42
42
  }
43
43
 
44
44
  export function getStartingSilentSampleCount(audioSamples: Float32Array, amplitudeThresholdDecibels = defaultSilenceThresholdDecibels) {
45
- const minSampleValue = decibelsToGain(amplitudeThresholdDecibels)
45
+ const minSampleAmplitude = decibelsToGainFactor(amplitudeThresholdDecibels)
46
46
 
47
47
  let silentSampleCount = 0
48
48
 
49
49
  for (let i = 0; i < audioSamples.length - 1; i++) {
50
- if (Math.abs(audioSamples[i]) > minSampleValue) {
50
+ if (Math.abs(audioSamples[i]) > minSampleAmplitude) {
51
51
  break
52
52
  }
53
53
 
@@ -58,12 +58,12 @@ export function getStartingSilentSampleCount(audioSamples: Float32Array, amplitu
58
58
  }
59
59
 
60
60
  export function getEndingSilentSampleCount(audioSamples: Float32Array, amplitudeThresholdDecibels = defaultSilenceThresholdDecibels) {
61
- const minSampleValue = decibelsToGain(amplitudeThresholdDecibels)
61
+ const minSampleAmplitude = decibelsToGainFactor(amplitudeThresholdDecibels)
62
62
 
63
63
  let silentSampleCount = 0
64
64
 
65
65
  for (let i = audioSamples.length - 1; i >= 0; i--) {
66
- if (Math.abs(audioSamples[i]) > minSampleValue) {
66
+ if (Math.abs(audioSamples[i]) > minSampleAmplitude) {
67
67
  break
68
68
  }
69
69
 
@@ -83,14 +83,14 @@ export function downmixToMonoAndNormalize(rawAudio: RawAudio, targetPeakDb = -3)
83
83
  export function normalizeAudioLevel(rawAudio: RawAudio, targetPeakDb = -3, maxIncreaseDb = 30): RawAudio {
84
84
  //rawAudio = correctDCBias(rawAudio)
85
85
 
86
- const targetPeakSampleValue = decibelsToGain(targetPeakDb)
87
- const maxMultiplier = decibelsToGain(maxIncreaseDb)
86
+ const targetPeakAmplitude = decibelsToGainFactor(targetPeakDb)
87
+ const maxGainFactor = decibelsToGainFactor(maxIncreaseDb)
88
88
 
89
- const maxAbsoluteSampleValue = getAudioPeakGain(rawAudio.audioChannels)
89
+ const peakAmplitude = getAudioPeakAmplitude(rawAudio.audioChannels)
90
90
 
91
- const multiplier = Math.min(targetPeakSampleValue / maxAbsoluteSampleValue, maxMultiplier)
91
+ const gainFactor = Math.min(targetPeakAmplitude / peakAmplitude, maxGainFactor)
92
92
 
93
- return applyGain(rawAudio, multiplier)
93
+ return applyGain(rawAudio, gainFactor)
94
94
  }
95
95
 
96
96
  export function correctDCBias(rawAudio: RawAudio): RawAudio {
@@ -120,21 +120,19 @@ export function correctDCBias(rawAudio: RawAudio): RawAudio {
120
120
  }
121
121
 
122
122
  export function applyGainDecibels(rawAudio: RawAudio, decibelGain: number): RawAudio {
123
- return applyGain(rawAudio, decibelsToGain(decibelGain))
123
+ return applyGain(rawAudio, decibelsToGainFactor(decibelGain))
124
124
  }
125
125
 
126
- export function applyGain(rawAudio: RawAudio, gain: number): RawAudio {
126
+ export function applyGain(rawAudio: RawAudio, gainFactor: number): RawAudio {
127
127
  const outputAudioChannels: Float32Array[] = []
128
128
 
129
- const multiplier = gain
130
-
131
129
  for (const channelSamples of rawAudio.audioChannels) {
132
130
  const sampleCount = channelSamples.length
133
131
 
134
132
  const outputChannelSamples = new Float32Array(sampleCount)
135
133
 
136
134
  for (let i = 0; i < sampleCount; i++) {
137
- outputChannelSamples[i] = channelSamples[i] * multiplier
135
+ outputChannelSamples[i] = channelSamples[i] * gainFactor
138
136
  }
139
137
 
140
138
  outputAudioChannels.push(outputChannelSamples)
@@ -158,19 +156,19 @@ export function downmixToMono(rawAudio: RawAudio): RawAudio {
158
156
  }
159
157
 
160
158
  export function getAudioPeakDecibels(audioChannels: Float32Array[]) {
161
- return gainToDecibels(getAudioPeakGain(audioChannels))
159
+ return gainFactorToDecibels(getAudioPeakAmplitude(audioChannels))
162
160
  }
163
161
 
164
- export function getAudioPeakGain(audioChannels: Float32Array[]) {
165
- let maxAbsoluteSampleValue = 0.00001
162
+ export function getAudioPeakAmplitude(audioChannels: Float32Array[]) {
163
+ let maxAmplitude = 0.00001
166
164
 
167
165
  for (const channelSamples of audioChannels) {
168
166
  for (const sample of channelSamples) {
169
- maxAbsoluteSampleValue = Math.max(maxAbsoluteSampleValue, Math.abs(sample))
167
+ maxAmplitude = Math.max(maxAmplitude, Math.abs(sample))
170
168
  }
171
169
  }
172
170
 
173
- return maxAbsoluteSampleValue
171
+ return maxAmplitude
174
172
  }
175
173
 
176
174
  export function mixAudio(rawAudio1: RawAudio, rawAudio2: RawAudio) {
@@ -252,7 +250,7 @@ export function fadeAudioInOut(rawAudio: RawAudio, fadeTime: number): RawAudio {
252
250
  const fadeSampleCount = Math.floor(rawAudio.sampleRate * fadeTime)
253
251
  const gainReductionPerFrameDecibels = -60 / fadeSampleCount
254
252
 
255
- const gainReductionPerFrameMultiplier = decibelsToGain(gainReductionPerFrameDecibels)
253
+ const gainReductionPerFrameFactor = decibelsToGainFactor(gainReductionPerFrameDecibels)
256
254
 
257
255
  const outAudioChannels = rawAudio.audioChannels.map(channel => channel.slice())
258
256
 
@@ -261,18 +259,20 @@ export function fadeAudioInOut(rawAudio: RawAudio, fadeTime: number): RawAudio {
261
259
  continue
262
260
  }
263
261
 
264
- let multiplier = 1.0
262
+ let factor = 1.0
265
263
 
266
264
  for (let i = fadeSampleCount - 1; i >= 0; i--) {
267
- channel[i] *= multiplier
268
- multiplier *= gainReductionPerFrameMultiplier
265
+ channel[i] *= factor
266
+
267
+ factor *= gainReductionPerFrameFactor
269
268
  }
270
269
 
271
- multiplier = 1.0
270
+ factor = 1.0
272
271
 
273
272
  for (let i = channel.length - fadeSampleCount; i < channel.length; i++) {
274
- channel[i] *= multiplier
275
- multiplier *= gainReductionPerFrameMultiplier
273
+ channel[i] *= factor
274
+
275
+ factor *= gainReductionPerFrameFactor
276
276
  }
277
277
  }
278
278
 
@@ -352,11 +352,11 @@ export async function ensureRawAudio(input: AudioSourceParam, outSampleRate?: nu
352
352
  // Unit conversion
353
353
  ////////////////////////////////////////////////////////////////////////////////////////////////
354
354
 
355
- export function gainToDecibels(gain: number) {
356
- return gain <= 0.00001 ? -100 : (20.0 * Math.log10(gain))
355
+ export function gainFactorToDecibels(gainFactor: number) {
356
+ return gainFactor <= 0.00001 ? -100 : (20.0 * Math.log10(gainFactor))
357
357
  }
358
358
 
359
- export function decibelsToGain(decibels: number) {
359
+ export function decibelsToGainFactor(decibels: number) {
360
360
  return decibels <= -100.0 ? 0 : Math.pow(10, 0.05 * decibels)
361
361
  }
362
362
 
@@ -1,24 +1,31 @@
1
- import path from "path"
2
- import { loadPackage } from "../utilities/PackageManager.js"
3
- import { commandExists } from "../utilities/Utilities.js"
1
+ import path from 'path'
2
+ import { loadPackage } from '../utilities/PackageManager.js'
3
+ import { commandExists } from '../utilities/Utilities.js'
4
+ import { getGlobalOption } from '../api/GlobalOptions.js'
4
5
 
5
6
  export async function tryResolvingSoxPath() {
6
- let soxPath: string | undefined = undefined
7
+ if (getGlobalOption('soxPath')) {
8
+ return getGlobalOption('soxPath')
9
+ }
10
+
11
+ const platform = process.platform
12
+ const arch = process.arch
7
13
 
8
- if (process.platform == "win32") {
9
- const soxPackagePath = await loadPackage("sox-14.4.1a-win32")
10
- soxPath = path.join(soxPackagePath, "sox.exe")
14
+ if (platform === 'win32') {
15
+ const soxPackagePath = await loadPackage('sox-14.4.1a-win32')
16
+
17
+ return path.join(soxPackagePath, 'sox.exe')
11
18
  }
12
- /*else if (process.platform == "darwin" && process.arch == "x64") {
13
- const soxPackagePath = await loadPackage("sox-14.4.1-macosx")
14
- soxPath = path.join(soxPackagePath, "sox")
15
- } */
16
- else if (process.platform == "linux" && process.arch == "x64") {
17
- const soxPackagePath = await loadPackage("sox-14.4.2-linux-minimal")
18
- soxPath = path.join(soxPackagePath, "sox")
19
- } else if (await commandExists("sox")) {
20
- soxPath = "sox"
19
+
20
+ if (await commandExists('sox')) {
21
+ return 'sox'
22
+ }
23
+
24
+ if (platform === 'linux' && arch === 'x64') {
25
+ const soxPackagePath = await loadPackage('sox-14.4.2-linux-minimal')
26
+
27
+ return path.join(soxPackagePath, 'sox')
21
28
  }
22
29
 
23
- return soxPath
30
+ return undefined
24
31
  }
@@ -6,6 +6,7 @@ import { Logger } from "../utilities/Logger.js"
6
6
  import { commandExists, logToStderr } from "../utilities/Utilities.js"
7
7
  import path from "node:path"
8
8
  import { loadPackage } from "../utilities/PackageManager.js"
9
+ import { getGlobalOption } from "../api/GlobalOptions.js"
9
10
 
10
11
  const log = logToStderr
11
12
 
@@ -147,25 +148,53 @@ function buildCommandLineArguments(inputFilename: string, outputOptions: FFMpegO
147
148
  }
148
149
 
149
150
  async function getFFMpegExecutablePath() {
150
- if (process.platform == "win32") {
151
- const ffmpegPackagePath = await loadPackage("ffmpeg-6.0-essentials-win64")
152
-
153
- return path.join(ffmpegPackagePath, "ffmpeg.exe")
151
+ // If a global option set for the path, use it
152
+ if (getGlobalOption('ffmpegPath')) {
153
+ return getGlobalOption('ffmpegPath')
154
+ }
155
+
156
+ // If an 'ffmpeg' command exist in system path, use it
157
+ if (await commandExists('ffmpeg')) {
158
+ return 'ffmpeg'
159
+ }
160
+
161
+ // Otherwise, download and use an internal ffmpeg package
162
+ const platform = process.platform
163
+ const arch = process.arch
164
+
165
+ let packageName: string
166
+
167
+ if (platform === 'win32' && arch === 'x64') {
168
+ packageName = 'ffmpeg-6.0-win32-x64'
169
+ } else if (platform === 'win32' && arch === 'ia32') {
170
+ packageName = 'ffmpeg-6.0-win32-ia32'
171
+ } else if (platform === 'darwin' && arch === 'x64') {
172
+ packageName = 'ffmpeg-6.0-darwin-x64'
173
+ } else if (platform === 'darwin' && arch === 'arm64') {
174
+ packageName = 'ffmpeg-6.0-darwin-arm64'
175
+ } else if (platform === 'linux' && arch === 'x64') {
176
+ packageName = 'ffmpeg-6.0-linux-x64'
177
+ } else if (platform === 'linux' && arch === 'ia32') {
178
+ packageName = 'ffmpeg-6.0-linux-ia32'
179
+ } else if (platform === 'linux' && arch === 'arm64') {
180
+ packageName = 'ffmpeg-6.0-linux-arm64'
181
+ } else if (platform === 'linux' && arch === 'arm') {
182
+ packageName = 'ffmpeg-6.0-linux-arm'
183
+ } else if (platform === 'freebsd' && arch === 'x64') {
184
+ packageName = 'ffmpeg-6.0-freebsd-x64'
185
+ } else {
186
+ return undefined
154
187
  }
155
- /* else if (process.platform == "darwin" && process.arch == "x64") {
156
- const ffmpegPackagePath = await loadPackage("ffmpeg-6.0-macos64")
157
188
 
158
- return path.join(ffmpegPackagePath, "ffmpeg")
159
- }
160
- */ else if (process.platform == "linux" && process.arch == "x64") {
161
- const ffmpegPackagePath = await loadPackage("ffmpeg-6.0-linux-amd64")
189
+ const ffmpegPackagePath = await loadPackage(packageName)
190
+
191
+ let filename = packageName
162
192
 
163
- return path.join(ffmpegPackagePath, "ffmpeg")
164
- } else if (await commandExists("ffmpeg")) {
165
- return "ffmpeg"
193
+ if (platform === 'win32') {
194
+ filename += '.exe'
166
195
  }
167
196
 
168
- return undefined
197
+ return path.join(ffmpegPackagePath, filename)
169
198
  }
170
199
 
171
200
  export function getDefaultFFMpegOptionsForSpeech(fileExtension: string, customBitrate?: number) {
@@ -293,6 +293,12 @@ export const voiceList: SynthesisVoice[] = [
293
293
  languages: ["de-DE", "de"],
294
294
  gender: "male",
295
295
  },
296
+ {
297
+ name: "de_DE-mls-medium",
298
+ languages: ["de-DE", "de"],
299
+ gender: "unknown",
300
+ speakerCount: 236
301
+ },
296
302
 
297
303
  {
298
304
  name: "el_GR-rapunzelina-low",
@@ -353,6 +359,12 @@ export const voiceList: SynthesisVoice[] = [
353
359
  languages: ["en-GB", "en"],
354
360
  gender: "female",
355
361
  },
362
+ {
363
+ name: "en_GB-cori-high",
364
+ languages: ["en-GB", "en"],
365
+ gender: "female",
366
+ },
367
+
356
368
 
357
369
  {
358
370
  name: "en_US-amy-low",
@@ -443,6 +455,21 @@ export const voiceList: SynthesisVoice[] = [
443
455
  languages: ["en-US", "en"],
444
456
  gender: "female",
445
457
  },
458
+ {
459
+ name: "en_US-kristin-medium",
460
+ languages: ["en-US", "en"],
461
+ gender: "female",
462
+ },
463
+ {
464
+ name: "en_US-ljspeech-high",
465
+ languages: ["en-US", "en"],
466
+ gender: "female",
467
+ },
468
+ {
469
+ name: "en_US-ljspeech-medium",
470
+ languages: ["en-US", "en"],
471
+ gender: "female",
472
+ },
446
473
 
447
474
  {
448
475
  name: "es_ES-carlfm-x_low",
@@ -476,6 +503,23 @@ export const voiceList: SynthesisVoice[] = [
476
503
  languages: ["es-MX", "es"],
477
504
  gender: "male",
478
505
  },
506
+ {
507
+ name: "es_MX-claude-high",
508
+ languages: ["es-MX", "es"],
509
+ gender: "female",
510
+ },
511
+
512
+ {
513
+ name: "fa_IR-amir-medium",
514
+ languages: ["fa_IR", "fa"],
515
+ gender: "male",
516
+ },
517
+ {
518
+ name: "fa_IR-gyro-medium",
519
+ languages: ["fa_IR", "fa"],
520
+ gender: "male",
521
+ },
522
+
479
523
 
480
524
  {
481
525
  name: "fi_FI-harri-low",
@@ -514,6 +558,17 @@ export const voiceList: SynthesisVoice[] = [
514
558
  gender: "unknown",
515
559
  speakerCount: 2
516
560
  },
561
+ {
562
+ name: "fr_FR-mls-medium",
563
+ languages: ["fr-FR", "fr"],
564
+ gender: "unknown",
565
+ speakerCount: 125
566
+ },
567
+ {
568
+ name: "fr_FR-tom-medium",
569
+ languages: ["fr-FR", "fr"],
570
+ gender: "male",
571
+ },
517
572
 
518
573
  {
519
574
  name: "hu_HU-anna-medium",
@@ -605,6 +660,12 @@ export const voiceList: SynthesisVoice[] = [
605
660
  languages: ["nl-NL", "nl"],
606
661
  gender: "female",
607
662
  },
663
+ {
664
+ name: "nl_NL-mls-medium",
665
+ languages: ["nl-NL", "nl"],
666
+ gender: "unknown",
667
+ speakerCount: 52,
668
+ },
608
669
 
609
670
  {
610
671
  name: "nl_BE-nathalie-x_low",
@@ -705,6 +766,12 @@ export const voiceList: SynthesisVoice[] = [
705
766
  gender: "female",
706
767
  },
707
768
 
769
+ {
770
+ name: "sl_SI-artur-medium",
771
+ languages: ["sl_SI", "sl"],
772
+ gender: "male",
773
+ },
774
+
708
775
  {
709
776
  name: "sr_RS-serbski_institut-medium",
710
777
  languages: ["sr-RS", "sr"],
@@ -734,6 +801,11 @@ export const voiceList: SynthesisVoice[] = [
734
801
  languages: ["tr-TR", "tr"],
735
802
  gender: "male",
736
803
  },
804
+ {
805
+ name: "tr_TR-fettah-medium",
806
+ languages: ["tr-TR", "tr"],
807
+ gender: "male",
808
+ },
737
809
 
738
810
  {
739
811
  name: "uk_UA-lada-x_low",