From 281aa1275b843699d58f8c0c1d9ad0fb637a0886 Mon Sep 17 00:00:00 2001 From: Tai Groot Date: Tue, 18 Apr 2023 14:53:39 -0700 Subject: [PATCH] update tts for non-stream --- client/tts.go | 95 ++++++++++++++++++++++++++++++++++++++++--- client/types/types.go | 5 +++ 2 files changed, 94 insertions(+), 6 deletions(-) diff --git a/client/tts.go b/client/tts.go index 630fe1a..2efd197 100644 --- a/client/tts.go +++ b/client/tts.go @@ -1,21 +1,104 @@ package client import ( + "bufio" + "bytes" "context" + "encoding/json" + "errors" + "fmt" "io" + "net/http" "strings" "github.com/taigrr/elevenlabs/client/types" ) -func (c Client) TextToSpeechV1TextToSpeechVoiceIdPostWriter(ctx context.Context, w io.Writer, voiceID string, options types.SynthesisOptions) ([]byte, error) { - localVarHttpMethod = strings.ToUpper("Post") - localVarPath := a.client.cfg.BasePath + "/v1/text-to-speech/{voice_id}" +func (c Client) TTSWriter(ctx context.Context, w io.Writer, text, voiceID string, options types.SynthesisOptions) error { + url := fmt.Sprintf(c.endpoint+"/v1/text-to-speech/%s", voiceID) + opts := types.TTS{ + Text: text, + VoiceSettings: options, + } + b, _ := json.Marshal(opts) + client := &http.Client{} + req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewBuffer(b)) + if err != nil { + return err + } + req.Header.Set("xi-api-key", c.apiKey) + req.Header.Set("User-Agent", "github.com/taigrr/elevenlabs") + req.Header.Set("accept", "audio/mpeg") + res, err := client.Do(req) + + switch res.StatusCode { + case 422: + ve := types.ValidationError{} + defer res.Body.Close() + jerr := json.NewDecoder(res.Body).Decode(&ve) + if jerr != nil { + err = errors.Join(err, jerr) + } else { + err = errors.Join(err, ve) + } + return err + case 401: + return ErrUnauthorized + case 200: + if err != nil { + return err + } + defer res.Body.Close() + io.Copy(w, res.Body) + return nil + default: + return errors.Join(err, ErrUnspecified) + } } -func (c Client) TextToSpeechV1TextToSpeechVoiceIdPost(ctx context.Context, voiceID string, options types.SynthesisOptions) ([]byte, error) { - localVarHttpMethod = strings.ToUpper("Post") - localVarPath := a.client.cfg.BasePath + "/v1/text-to-speech/{voice_id}" +func (c Client) TTS(ctx context.Context, w io.Writer, text, voiceID string, options types.SynthesisOptions) ([]byte, error) { + url := fmt.Sprintf(c.endpoint+"/v1/text-to-speech/%s", voiceID) + client := &http.Client{} + opts := types.TTS{ + Text: text, + VoiceSettings: options, + } + b, _ := json.Marshal(opts) + req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewBuffer(b)) + if err != nil { + return []byte{}, err + } + req.Header.Set("xi-api-key", c.apiKey) + req.Header.Set("User-Agent", "github.com/taigrr/elevenlabs") + req.Header.Set("accept", "audio/mpeg") + res, err := client.Do(req) + + switch res.StatusCode { + case 422: + ve := types.ValidationError{} + defer res.Body.Close() + jerr := json.NewDecoder(res.Body).Decode(&ve) + if jerr != nil { + err = errors.Join(err, jerr) + } else { + err = errors.Join(err, ve) + } + return []byte{}, err + case 401: + return []byte{}, ErrUnauthorized + case 200: + if err != nil { + return []byte{}, err + } + b := bytes.Buffer{} + w := bufio.NewWriter(&b) + + defer res.Body.Close() + io.Copy(w, res.Body) + return b.Bytes(), nil + default: + return []byte{}, errors.Join(err, ErrUnspecified) + } } func (c Client) TextToSpeechV1TextToSpeechVoiceIdStreamPost(ctx context.Context, w io.Writer, voiceId string, options types.SynthesisOptions) error { diff --git a/client/types/types.go b/client/types/types.go index 7c0ed9b..22a3763 100644 --- a/client/types/types.go +++ b/client/types/types.go @@ -25,6 +25,11 @@ type TTS struct { VoiceSettings SynthesisOptions `json:"voice_settings,omitempty"` // Voice settings are applied only on the given TTS request. } +var DefaultSynthesisOptions = SynthesisOptions{ + Stability: 75, + SimilarityBoost: 75, +} + type SynthesisOptions struct { Stability float64 `json:"stability"` SimilarityBoost float64 `json:"similarity_boost"`