文章目录
背景
在之前文章中我们对chattts有了一个大致的了解并对webui进行了一定的优化。然而,还有很多情况下我们还需要进行api调用。gradio虽然也提供了sdk,但只有python和node两种语言,远远不如http接口来的泛用。因此,我们来对chatts更近一步优化,来编写一个apiServer。
技术方案
技术方案我们选用FastAPI。
我们对FastAPI做一个简要的介绍
fastapi
,一个用于构建 API 的现代、快速(高性能)的web框架。
fastapi
是建立在Starlette和Pydantic基础上的,Pydantic是一个基于Python类型提示来定义数据验证、序列化和文档的库。Starlette是一种轻量级的ASGI框架/工具包,是构建高性能Asyncio服务的理性选择。
- 快速:可与 NodeJS 和 Go 比肩的
极高性能
(归功于Starlette
和Pydantic
),是最快的 Python web 框架之一。- 高效编码:提高功能开发速度约 200% 至 300%。
- 更少bug:减少约 40% 的人为(开发者)导致错误。
- 智能:极佳的编辑器支持。处处皆可自动补全,减少调试时间。
- 简单:设计的
易于使用和学习
,阅读文档的时间更短。- 简短:使代码重复最小化。通过不同的参数声明实现丰富功能。
- 健壮:生产可用级别的代码。还有
自动生成的交互式文档
。
方案实现
安装FastAPI
pip install "fastapi[all]"
pip install "uvicorn[standard]"
编写一个入口
from fastapi import FastAPI # FastAPI 是一个为你的 API 提供了所有功能的 Python 类。
import uvicorn
app = FastAPI() # 这个实例将是创建你所有 API 的主要交互对象。这个 app 同样在如下命令中被 uvicorn 所引用
@app.get("/")
async def root():
return {"message": "Hello yuan"}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8087)
一个简单案例就做好了,和其它很多框架一样,我们需要引入路由分组
app = FastAPI()
app.include_router(prefix="/chat", router=audio_router)
不同分组就不再是通过app来修饰
router = APIRouter()
@router.post("/generate_audio")
async def generate_audio(request: GenerateAudioRequest):
...
逻辑实现
全局只维护一个chat对象
如何每次创建一个chat对象,显存将很快被耗完。每创建完一个对象大约消耗1GB显存,小于4GB显存将强制使用CPU进行推理
def create_chat(local_path=None):
"""创建ChatTTS实例"""
if "chat" in cf:
logging.info("cached chat")
return cf['chat']
local_model_path = os.getenv('MODEL_LOCAL_PATH', None)
# 导入模型实例
chat = ChatTTS.Chat()
if local_model_path is None:
chat.load_models()
else:
logging.info('local model path:', local_model_path)
chat.load_models('local', local_path=local_model_path)
cf['chat'] = chat
return chat
生成随机音色
def determine_seed(seed):
"""限定模型使用的种子值"""
torch.manual_seed(seed)
np.random.seed(seed)
torch.cuda.manual_seed(seed)
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
def build_random_speaker(chat, request: GenerateAudioRequest):
"""
生成随机音色
:param chat:
:param request:
:return:
"""
# 使用音色种子值创建音色
audio_seed_input = request.audio_seed_input
determine_seed(audio_seed_input)
return chat.sample_random_speaker()
合成一个完整音频
# 将所有的语音片段合并成一个完整的音频
audio_data_all = np.concatenate(audio_data_all)
sample_rate = 24000
# 写入WAV文件
file_name = wav_utils.build_wav_name()
file_path = str(Path(global_info.AUDIO_TEMP_PATH).joinpath(file_name).resolve())
wavfile.write(file_path, sample_rate, audio_data_all)
返回结果
在每次音频生成结束后,返回音频名称,并将tensor等参数一并返回,方便保存
return {
"out_put_text": "\n".join(text_data_all),
"audio_name": file_name,
"tensor": speak_tensor.tolist()
}
总结
我们可以根据这些核心需求编写chattts的服务端,满足自己的接口调用需求。本文代码见
# 总结
我们可以根据这些核心需求编写chattts的服务端,满足自己的接口调用需求。本文代码见
[chatts-manger](https://github.com/MaterialShadow/ChatTTS-manager/tree/master/apiServer)
标签:chatTTS,系列,FastAPI,apiServer,seed,chat,path,audio,local
From: https://blog.csdn.net/u012399690/article/details/139690829