mirror of
https://github.com/AlexxIT/go2rtc.git
synced 2025-09-26 20:31:11 +08:00
121 lines
2.1 KiB
Go
121 lines
2.1 KiB
Go
package wyoming
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/url"
|
|
)
|
|
|
|
type WakeWord struct {
|
|
*API
|
|
names []string
|
|
send int
|
|
|
|
Detection string
|
|
}
|
|
|
|
func DialWakeWord(rawURL string) (*WakeWord, error) {
|
|
u, err := url.Parse(rawURL)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
api, err := DialAPI(u.Host)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
names := u.Query()["name"]
|
|
if len(names) == 0 {
|
|
names = []string{"ok_nabu_v0.1"}
|
|
}
|
|
|
|
wake := &WakeWord{API: api, names: names}
|
|
if err = wake.Start(); err != nil {
|
|
_ = wake.Close()
|
|
return nil, err
|
|
}
|
|
|
|
go wake.handle()
|
|
return wake, nil
|
|
}
|
|
|
|
func (w *WakeWord) handle() {
|
|
defer w.Close()
|
|
|
|
for {
|
|
evt, err := w.ReadEvent()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
if evt.Type == "detection" {
|
|
var data struct {
|
|
Name string `json:"name"`
|
|
}
|
|
if err = json.Unmarshal([]byte(evt.Data), &data); err != nil {
|
|
return
|
|
}
|
|
w.Detection = data.Name
|
|
}
|
|
}
|
|
}
|
|
|
|
//func (w *WakeWord) Describe() error {
|
|
// if err := w.WriteEvent(&Event{Type: "describe"}); err != nil {
|
|
// return err
|
|
// }
|
|
//
|
|
// evt, err := w.ReadEvent()
|
|
// if err != nil {
|
|
// return err
|
|
// }
|
|
//
|
|
// var info struct {
|
|
// Wake []struct {
|
|
// Models []struct {
|
|
// Name string `json:"name"`
|
|
// } `json:"models"`
|
|
// } `json:"wake"`
|
|
// }
|
|
// if err = json.Unmarshal(evt.Data, &info); err != nil {
|
|
// return err
|
|
// }
|
|
//
|
|
// return nil
|
|
//}
|
|
|
|
func (w *WakeWord) Start() error {
|
|
msg := struct {
|
|
Names []string `json:"names"`
|
|
}{
|
|
Names: w.names,
|
|
}
|
|
data, err := json.Marshal(msg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
evt := &Event{Type: "detect", Data: string(data)}
|
|
if err := w.WriteEvent(evt); err != nil {
|
|
return err
|
|
}
|
|
|
|
evt = &Event{Type: "audio-start", Data: audioData(0)}
|
|
return w.WriteEvent(evt)
|
|
}
|
|
|
|
func (w *WakeWord) Close() error {
|
|
return w.conn.Close()
|
|
}
|
|
|
|
func (w *WakeWord) WriteChunk(payload []byte) error {
|
|
evt := &Event{Type: "audio-chunk", Data: audioData(w.send), Payload: payload}
|
|
w.send += len(payload)
|
|
return w.WriteEvent(evt)
|
|
}
|
|
|
|
func audioData(send int) string {
|
|
// timestamp in ms = send / 2 * 1000 / 16000 = send / 32
|
|
return fmt.Sprintf(`{"rate":16000,"width":2,"channels":1,"timestamp":%d}`, send/32)
|
|
}
|