Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
sudoskys committed Dec 21, 2022
2 parents 3cefec4 + d1898bb commit f7f3149
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 20 deletions.
53 changes: 44 additions & 9 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ public class HMACSHA256Example {
| groupId | Integer || 如果该请求在群聊中发起,此参数可用于标识来源群聊 | 1919810 | 0 |
| timestamp | Integer || 用于标识请求发起时间,应为秒级时间戳(10位整数) | 1671441081 | 0 |
| signature | String || 接口签名 | (略) | "" |
| returnVoice | Bool || chat、write接口专属功能。是否将AI返回合成为语音 | false | false |
| returnVoiceRaw | Bool || chat、write接口专属功能。合成语音时,是否输出原始wav文件(而不是base64编码) | true | true |
| returnVoice | Bool || chat、write接口专属功能。是否将AI返回合成为语音。此项已被用户在/voice接口中的设置覆盖,您现在无需传入此参数。 | false | false |
| returnVoiceRaw | Bool || chat、write接口专属功能。合成语音时,是否输出原始wav文件(而不是wav的base64编码)由于各项目代码逻辑不同,您仍需在请求时传入此参数。 | true | true |

实际请求时对数据类型的要求不是很严格。如若对timestamp传入字符串类型的时间戳,API将自动转换为整数。

Expand All @@ -175,12 +175,12 @@ Connection: keep-alive

在returnVoiceRaw = false且正常合成语音时,本API所有接口都以json格式响应(已转义),编码UTF-8。格式如下:

| 参数名 | 数据类型 | 解释 | 示例数据 |
| ------------ | -------- | ------------------------------------------------------------ | ------------------------------------------------------ |
| success | Bool | 本次请求是否成功 | true |
| response | String | 对本次请求的返回文本或音频Base64。若success=false,则本参数为请求出错原因。 | "喵~ 你好啊,主人!很高兴见到你!有什么能帮助你的吗?" |
| isVITSFailed | Bool | 语音合成是否失败。若失败,response将返回对话文本,您应在服务器控制台查看错误信息。未合成语音时不返回此参数。 | false |
| text | String | 合成的语音所对应的文本。未合成语音时不返回此参数。 | "您好!很高兴为您服务,请问有什么我可以帮您的?" |
| 参数名 | 数据类型 | 解释 | 示例数据 |
| ----------- | -------- | ------------------------------------------------------------ | ------------------------------------------------------ |
| success | Bool | 本次请求是否成功 | true |
| response | String | 对本次请求的返回文本或音频Base64。若success=false,则本参数为请求出错原因。 | "喵~ 你好啊,主人!很高兴见到你!有什么能帮助你的吗?" |
| isTTSFailed | Bool | 语音合成是否失败。若失败,response将返回对话文本,您应在服务器控制台查看错误信息。未合成语音时不返回此参数。 | false |
| text | String | 合成的语音所对应的文本。未合成语音时不返回此参数。 | "您好!很高兴为您服务,请问有什么我可以帮您的?" |

当success = false时,response所有可能的返回值如下:

Expand All @@ -196,6 +196,7 @@ Connection: keep-alive
| OPERATION_NOT_PERMITTED | 在执行管理指令时出现。当前chatId不是机器人管理员。 |
| INVAILD_ADMIN_ACTION | 所指定的管理操作无效。 |
| GENERAL_FAILURE | 不知道发生了什么,总之就是出错了。错误信息通常已输出到控制台,请通过终端查看。 |
| DISABLED | 服务未开启,不处理任何请求。请通过/admin/open接口开启服务。 |

请注意,当您的请求体无效时(如未转义双引号导致请求json格式错误),您的请求会被FastAPI截胡并返回FastAPI生成的json报错。此情况下的响应参数请参阅FastAPI文档。

Expand Down Expand Up @@ -238,7 +239,7 @@ Content-type: audio/x-pcm
"groupId": "1919810",
"signature": "no sign",
"timestamp": "1671266252",
"returnVoice": true,
"returnVoice": true, // returnVoice现已被/voice接口接管,无需传入
"returnVoiceRaw": false
}
// 响应2:合成语音(Base64)
Expand Down Expand Up @@ -267,6 +268,40 @@ Content-type: audio/x-pcm
}
```

### (POST) /voice 语音合成开关

```java
// 请求1:切换语音合成
{
"chatText": "无参,爱写啥写啥",
"chatId": "114514",
"groupId": "1919810",
"signature": "no sign",
"timestamp": "1671266252"
}
// 响应1:切换语音合成
{
"success": true,
"response": "TTS Status: True"
}

// 请求2:合成语音(/chat)
{
"chatText": "你好",
"chatId": "114514",
"groupId": "1919810",
"signature": "no sign",
"timestamp": "1671266252",
"returnVoiceRaw": false
}
// 响应2:合成语音(/chat)
{
"success": true,
"response": "(wav语音Base64)",
"text": "你好哥哥!很高兴认识你!有什么可以与你分享的吗?"
}
```

### (POST) /remind 场景设定

```java
Expand Down
9 changes: 7 additions & 2 deletions API/Voice.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ async def vits(text, task:int = 1, doReturnRawAudio: bool = True):
if(Talk.get_language(text) != 'chinese'):
logger.warning('语言不支持。语音合成目前仅支持合成中文')
return False
newtext = '[ZH]' + text + '[ZH]'
text = Talk.chinese_sentence_cut(text)
cn = {i: "[ZH]" for i in text}
_spell = [f"{cn[x]}{x}{cn[x]}" for x in cn.keys()]
newtext = "".join(_spell)
reqbody = TTS_REQ(model_name = vitsConf['model_name'],
task_id = task,
text = newtext,
Expand Down Expand Up @@ -50,4 +53,6 @@ async def get(self, text, task:int = 1, doReturnRawAudio:bool = True):
if(ttsType == 'vits'):
return await VITS.vits(text, task, doReturnRawAudio)
elif(ttsType == 'azure'):
return await VITS.azure(text, doReturnRawAudio)
return await VITS.azure(text, doReturnRawAudio)
else:
return False
34 changes: 26 additions & 8 deletions APIServer.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import os
from API.FakeMessage import FakeTGBotMessage, FakeTGBot
from API.Voice import VITS
from utils.Chat import UserManger

class ReqBody(BaseModel):
chatText: str = ''
Expand All @@ -29,7 +30,9 @@ class ReqBody(BaseModel):
config = ReadConfig().parseFile(os.path.split(os.path.realpath(__file__))[0] + '/Config/app.toml')
_csonfig = appe.load_csonfig()

def checkIllegal(reqbody):
def preCheck(reqbody):
if(not _csonfig['statu']):
return {'success': False, 'message': 'DISABLED'}
message = FakeTGBotMessage()
message.from_user.id = reqbody.chatId
message.chat.id = reqbody.groupId
Expand All @@ -44,6 +47,8 @@ def checkIllegal(reqbody):
if(apicfg['doValidateTimestamp']):
if(abs(int(time.time()) - reqbody.timestamp) > apicfg['RequestTimeout']):
return {'success': False,'response': 'TIMESTAMP_OUTDATED'}
if(UserManger(int(reqbody.chatId)).read('voice')):
reqbody.returnVoice = True
# Request body is NOT ILLEGAL, so false
return False

Expand All @@ -57,7 +62,7 @@ def read_root():
#### Chat
@app.post('/chat')
async def chat(body: ReqBody):
if(response := checkIllegal(body)):
if(response := preCheck(body)):
return response
try:
if(body.chatId and body.chatText):
Expand All @@ -72,7 +77,7 @@ async def chat(body: ReqBody):
if(vresp):
return vresp
else:
return {'success': True, 'response': res, 'isVITSFailed': True}
return {'success': True, 'response': res, 'isTTSFailed': True}
return {'success': True, 'response': res}
else:
return {'success': False, 'response':'INVAILD_CHATINFO'}
Expand All @@ -82,7 +87,7 @@ async def chat(body: ReqBody):
#### Write
@app.post('/write')
async def write(body: ReqBody):
if(response := checkIllegal(body)):
if(response := preCheck(body)):
return response
try:
if(body.chatId and body.chatText):
Expand All @@ -98,18 +103,31 @@ async def write(body: ReqBody):
if(vresp):
return vresp
else:
return {'success': True, 'response': res, 'isVITSFailed': True}
return {'success': True, 'response': res, 'isTTSFailed': True}
return {'success': True, 'response':res}
else:
return {'success': False,'response':'INVAILD_CHATINFO'}
except Exception as e:
logger.error(e)

#### Voice
@app.post('/voice')
async def voice(body: ReqBody):
if(response := preCheck(body)):
return response
try:
user = UserManger(int(body.chatId))
doUserVoice = False if user.read('voice') else True
user.save({'voice': doUserVoice})
return {'success': True, 'response': 'TTS Status: ' + str(doUserVoice)}
except Exception as e:
logger.error(e)

#### Forget
@app.post('/forgetme')
async def forgetme(body: ReqBody):
try:
if(response := checkIllegal(body)):
if(response := preCheck(body)):
return response
message = FakeTGBotMessage()
message.from_user.id = body.chatId
Expand All @@ -125,7 +143,7 @@ async def forgetme(body: ReqBody):
@app.post('/remind')
async def remind(body: ReqBody):
try:
if(response := checkIllegal(body)):
if(response := preCheck(body)):
return response
if(not body.chatText):
return {'success': False,'response': 'INVAILD_CHATINFO'}
Expand All @@ -152,7 +170,7 @@ async def remind(body: ReqBody):
@app.post('/admin/{action}')
async def admin(body: ReqBody, action: str):
try:
if(response := checkIllegal(body)):
if(response := preCheck(body)):
return response
if(not body.chatId in config.bot.master):
return {'success': False,'response': 'OPERATION_NOT_PERMITTED'}
Expand Down
2 changes: 2 additions & 0 deletions App/Event.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ async def TTS_Support_Check(text, user_id):
lang_type = Talk.get_language(text)
if lang_type not in ["chinese"]:
return
if(_tts_conf['type'] == 'none'):
return
if _tts_conf["type"] == "vits":
_vits_config = _tts_conf["vits"]
if len(text) > _vits_config["limit"]:
Expand Down
2 changes: 1 addition & 1 deletion utils/Data.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def defaultService():
},
"tts": {
"status": True,
"type": "vits",
"type": "none",
"vits": {
"api": "http://127.0.0.1:9557/tts/generate",
"limit": 70,
Expand Down

0 comments on commit f7f3149

Please sign in to comment.