?say=XYZ to TTS
This commit is contained in:
@@ -2,7 +2,8 @@ package v01
|
||||
|
||||
type config struct {
|
||||
Feedback struct {
|
||||
Addr string
|
||||
Addr string
|
||||
TTSURL string
|
||||
}
|
||||
Users map[string]struct {
|
||||
Player int
|
||||
|
||||
@@ -79,10 +79,11 @@ func (v01 *V01) globalQueries(r *http.Request) {
|
||||
}
|
||||
|
||||
func (v01 *V01) globalQuerySay(r *http.Request) {
|
||||
if _, ok := r.URL.Query()["say"]; !ok {
|
||||
text := r.URL.Query().Get("say")
|
||||
if text == "" {
|
||||
return
|
||||
}
|
||||
// todo larynx
|
||||
go v01.tts(text)
|
||||
}
|
||||
|
||||
func (v01 *V01) globalQueryRefresh(r *http.Request) {
|
||||
|
||||
1
src/device/input/parse/v01/testdata/v01.yaml
vendored
1
src/device/input/parse/v01/testdata/v01.yaml
vendored
@@ -1,5 +1,6 @@
|
||||
feedback:
|
||||
addr: :17071
|
||||
ttsurl: http://localhost:15002
|
||||
users:
|
||||
bel:
|
||||
player: 0
|
||||
|
||||
64
src/device/input/parse/v01/tts.go
Normal file
64
src/device/input/parse/v01/tts.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package v01
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/faiface/beep"
|
||||
"github.com/faiface/beep/effects"
|
||||
"github.com/faiface/beep/speaker"
|
||||
"github.com/faiface/beep/wav"
|
||||
)
|
||||
|
||||
func (v01 *V01) tts(text string) {
|
||||
if err := v01._tts(text); err != nil {
|
||||
log.Printf("failed to tts: %s: %v", text, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (v01 *V01) _tts(text string) error {
|
||||
if v01.cfg.Feedback.TTSURL == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
url, err := url.Parse(v01.cfg.Feedback.TTSURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(url.Path) < 2 {
|
||||
url.Path = "/api/tts"
|
||||
}
|
||||
q := url.Query()
|
||||
if q.Get("voice") == "" {
|
||||
q.Set("voice", "en-us/glados-glow_tts")
|
||||
}
|
||||
if q.Get("lengthScale") == "" {
|
||||
q.Set("lengthScale", "1")
|
||||
}
|
||||
q.Set("text", text)
|
||||
url.RawQuery = q.Encode()
|
||||
|
||||
resp, err := http.Get(url.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
b, _ := io.ReadAll(resp.Body)
|
||||
if resp.StatusCode != http.StatusOK || resp.Header.Get("Content-Type") != "audio/wav" {
|
||||
return fmt.Errorf("failed to call ttsurl: (%d) %s", resp.StatusCode, b)
|
||||
}
|
||||
|
||||
decoder, format, err := wav.Decode(bytes.NewReader(b))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/30))
|
||||
speaker.Play(&effects.Volume{Streamer: beep.ResampleRatio(4, 1, &beep.Ctrl{Streamer: beep.Loop(1, decoder)})})
|
||||
return nil
|
||||
}
|
||||
@@ -84,6 +84,7 @@ func TestV01Feedback(t *testing.T) {
|
||||
os.WriteFile(p, []byte(`
|
||||
feedback:
|
||||
addr: :27071
|
||||
ttsurl: http://localhost:15002
|
||||
users:
|
||||
bel:
|
||||
player: 2
|
||||
@@ -156,6 +157,18 @@ func TestV01Feedback(t *testing.T) {
|
||||
t.Error(string(b))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("tts", func(t *testing.T) {
|
||||
if os.Getenv("INTEGRATION_TTS") != "true" {
|
||||
t.Skip("$INTEGRATION_TTS is not true")
|
||||
}
|
||||
resp, err := http.Get("http://localhost:27071/?say=hello%20world")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
time.Sleep(time.Second * 2)
|
||||
})
|
||||
}
|
||||
|
||||
type constSrc string
|
||||
|
||||
Reference in New Issue
Block a user