1
0
mirror of https://github.com/fumiama/ahsai.git synced 2026-06-04 23:30:24 +08:00
Files
ahsai/api.go
2022-08-07 22:49:51 +08:00

91 lines
2.3 KiB
Go

// Package ahsai AH Soft フリーテキスト音声合成 demo API
package ahsai
import (
"bytes"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"time"
)
const api = "https://cloud.ai-j.jp/demo/aitalk2webapi_nop.php?callback=callback&speaker_id=%d&text=%s&ext=ogg&volume=%.1f&speed=%.1f&pitch=%.1f&range=%.1f&anger=%.1f&sadness=%.1f&joy=%.1f&_=%d"
var (
speakers = map[string]uint32{
"琴葉葵": 551,
"琴葉茜": 552,
"紲星あかり": 554,
"吉田くん": 1201,
"東北ずん子": 1202,
"月読アイ": 1203,
"月読ショウタ": 1204,
"民安ともえ": 1205,
"結月ゆかり": 1206,
"水奈瀬コウ": 1207,
"京町セイカ": 1208,
"東北きりたん": 1209,
"桜乃そら": 1210,
"東北イタコ": 1211,
"ついなちゃん標準語": 1212,
"ついなちゃん関西弁": 1213,
"伊織弓鶴": 1214,
"音街ウナ": 2006,
}
)
// Speaker is a particular setting of the API
type Speaker struct {
id uint32
Volume, Speed, Pitch, Range, Anger, Sadness, Joy float32
}
// NewSpeaker init default para of a speaker.
// Use s.SetName() to set the real speaker.
func NewSpeaker() (s Speaker) {
s.Volume = 1
s.Speed = 1
s.Pitch = 1
s.Range = 1
return
}
var (
// ErrTextTooLong 文本超过 100 字
ErrTextTooLong = errors.New("text too long")
// ErrNoSuchSpeaker 查无此人
ErrNoSuchSpeaker = errors.New("no such speaker")
)
// SetName set the speaker id.
func (s *Speaker) SetName(name string) error {
id, ok := speakers[name]
if !ok {
return ErrNoSuchSpeaker
}
s.id = id
return nil
}
// Speak text, return ogg url
func (s *Speaker) Speak(text string) (string, error) {
if len([]rune(text)) > 100 {
return "", ErrTextTooLong
}
resp, err := http.Get(fmt.Sprintf(api, s.id, url.QueryEscape(text), s.Volume, s.Speed, s.Pitch, s.Range, s.Anger, s.Sadness, s.Joy, time.Now().UnixMilli()))
if err != nil {
return "", err
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
data = bytes.TrimPrefix(data, []byte(`callback({"url":"`))
data = bytes.TrimSuffix(data, []byte(`"})`))
data = bytes.ReplaceAll(data, []byte(`\/`), []byte(`/`))
return "https:" + string(data), nil
}