File size: 2,313 Bytes
811126d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
export class ElevenLabsClient {
  private apiKey: string;
  private baseUrl = "https://api.elevenlabs.io/v1";

  constructor(apiKey: string) {
    this.apiKey = apiKey;
  }

  async getVoices(): Promise<any[]> {
    const response = await fetch(`${this.baseUrl}/voices`, {
      headers: {
        "xi-api-key": this.apiKey,
      },
    });

    if (!response.ok) {
      throw new Error(`Failed to get voices: ${response.statusText}`);
    }

    const data = await response.json();
    return data.voices;
  }

  async deleteVoice(voiceId: string): Promise<void> {
    const response = await fetch(`${this.baseUrl}/voices/${voiceId}`, {
      method: "DELETE",
      headers: {
        "xi-api-key": this.apiKey,
      },
    });

    if (!response.ok) {
      console.error("ElevenLabs error:", await response.text());
      throw new Error(`Failed to delete voice: ${response.statusText}`);
    }
  }

  async addVoice(name: string, audioFile: File): Promise<string> {
    const formData = new FormData();
    formData.append("name", name);
    formData.append("files", audioFile);
    formData.append("description", "Voice generated for NotMe game");

    const response = await fetch(`${this.baseUrl}/voices/add`, {
      method: "POST",
      headers: {
        "xi-api-key": this.apiKey,
      },
      body: formData,
    });

    if (!response.ok) {
      console.error("ElevenLabs error:", await response.text());
      throw new Error(`Failed to add voice: ${response.statusText}`);
    }

    const data = await response.json();
    return data.voice_id;
  }

  async generateSpeech(voiceId: string, text: string): Promise<Buffer> {
    const response = await fetch(
      `${this.baseUrl}/text-to-speech/${voiceId}/stream`,
      {
        method: "POST",
        headers: {
          "xi-api-key": this.apiKey,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          text,
          model_id: "eleven_monolingual_v1",
          voice_settings: {
            stability: 0.5,
            similarity_boost: 0.75,
          },
        }),
      }
    );

    if (!response.ok) {
      throw new Error(`Failed to generate speech: ${response.statusText}`);
    }

    const arrayBuffer = await response.arrayBuffer();
    return Buffer.from(arrayBuffer);
  }
}