Update code to typescript

This commit is contained in:
2026-05-14 20:06:15 +02:00
parent fdb4b2d50f
commit f2ce38c176
68 changed files with 7647 additions and 5121 deletions

78
src/tts/google.ts Normal file
View File

@@ -0,0 +1,78 @@
import { existsSync } from "node:fs";
import { writeFile } from "node:fs/promises";
import textToSpeech from "@google-cloud/text-to-speech";
import type { TextToSpeechClient } from "@google-cloud/text-to-speech";
import { config } from "../config.js";
import { BaseEngine, type VoiceParams } from "./BaseEngine.js";
interface GoogleVoiceMeta {
name: string;
lang: string;
}
export class GoogleEngine extends BaseEngine {
private client: TextToSpeechClient | undefined;
protected override voices: Record<string, GoogleVoiceMeta> = {};
constructor() {
super("google", "Google Cloud TTS", "wav");
void this.populateVoiceList();
}
override getDefaultVoice(): string {
return "en-us-wavenet-a";
}
private credentialsAvailable(): boolean {
return (
!!config.GOOGLE_APPLICATION_CREDENTIALS &&
existsSync(config.GOOGLE_APPLICATION_CREDENTIALS)
);
}
private getClient(): TextToSpeechClient {
if (!this.credentialsAvailable()) {
throw new Error(
"Google Cloud TTS unavailable: GOOGLE_APPLICATION_CREDENTIALS must point to a readable file",
);
}
this.client ??= new textToSpeech.TextToSpeechClient();
return this.client;
}
private async populateVoiceList(): Promise<void> {
if (!this.credentialsAvailable()) return;
try {
const [result] = await this.getClient().listVoices({});
for (const voice of result.voices ?? []) {
if (!voice.name || !voice.languageCodes?.[0]) continue;
this.voices[voice.name.toLowerCase()] = {
name: voice.name,
lang: voice.languageCodes[0],
};
}
} catch (err) {
console.error("Google Cloud TTS: failed to populate voice list:", err);
}
}
override async getSpeechFile(
text: string,
filepath: string,
voice: string = this.getDefaultVoice(),
_params: VoiceParams = {},
): Promise<string> {
const meta = this.voices[voice];
if (!meta) throw new Error(`Google: unknown voice "${voice}"`);
const [response] = await this.getClient().synthesizeSpeech({
input: { text },
voice: { name: meta.name, languageCode: meta.lang },
audioConfig: { audioEncoding: "LINEAR16" },
});
if (!response.audioContent) {
throw new Error("Google: synthesizeSpeech returned no audioContent");
}
await writeFile(filepath, response.audioContent);
return filepath;
}
}