You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

54 lines
1.4 KiB

11 months ago
  1. const { ElevenLabsClient, stream } = require("elevenlabs");
  2. class ElevenLabsTTS {
  3. constructor() {
  4. if (!process.env.TTS_ELEVEN_LABS_KEY)
  5. throw new Error("No ElevenLabs API key was set.");
  6. this.elevenLabs = new ElevenLabsClient({
  7. apiKey: process.env.TTS_ELEVEN_LABS_KEY,
  8. });
  9. // Rachel as default voice
  10. // https://api.elevenlabs.io/v1/voices
  11. this.voiceId =
  12. process.env.TTS_ELEVEN_LABS_VOICE_MODEL ?? "21m00Tcm4TlvDq8ikWAM";
  13. this.modelId = "eleven_multilingual_v2";
  14. }
  15. static async voices(apiKey = null) {
  16. try {
  17. const client = new ElevenLabsClient({
  18. apiKey: apiKey ?? process.env.TTS_ELEVEN_LABS_KEY ?? null,
  19. });
  20. return (await client.voices.getAll())?.voices ?? [];
  21. } catch {}
  22. return [];
  23. }
  24. #stream2buffer(stream) {
  25. return new Promise((resolve, reject) => {
  26. const _buf = [];
  27. stream.on("data", (chunk) => _buf.push(chunk));
  28. stream.on("end", () => resolve(Buffer.concat(_buf)));
  29. stream.on("error", (err) => reject(err));
  30. });
  31. }
  32. async ttsBuffer(textInput) {
  33. try {
  34. const audio = await this.elevenLabs.generate({
  35. voice: this.voiceId,
  36. text: textInput,
  37. model_id: "eleven_multilingual_v2",
  38. });
  39. return Buffer.from(await this.#stream2buffer(audio));
  40. } catch (e) {
  41. console.error(e);
  42. }
  43. return null;
  44. }
  45. }
  46. module.exports = {
  47. ElevenLabsTTS,
  48. };