这段音频就是本文的接口生成的。

Python Web 开发方面有一个很重要的环节就是开发接口,开发接口性能最好的工具就是闪电侠 FastAPI[1],正如它的名字一样,是非常快的 API。当然,还有一些 REST API 框架,如 Django REST Framework,Flask-RESTful 等,如果以性能为首要考虑因素,那毫无疑问选择 FastAPI。

结合现在比较流行的文本转语音的应用场景,本文展示如何用 FastAPI 来快速开发一个文本转语音的接口,其中详细罗列了每一步骤,让你学会开发 Web 接口,学不会你找我「微信 somenzz」。

主要内容:

  • 先写出主要的函数

  • 将函数转化为 Web API

  • 写个前端界面

  • 发布成 Docker 镜像

1、先写出主要的函数

首先分析下这个需求,文本转语音接口有两个功能点,一个是将文件转成语音,另一个是下载语音文件,将这两个功能先写两个简单函数,然后逐步细化。

def convert_text_to_voice(text: str) -> str:"""将文件转成语音文件,返回语音文件的文件名"""file_name = text_to_voice(text) # text_to_voice 负责将 text 转成语音文件,后面再实现    return file_namedef download_file(filename: str):"""返回一下 FileResponse 对象"""return 文件对象

上述代码中有个 text_to_voice 函数,其逻辑就是将文本转语音文件,返回其文件名,由于文件名并不是使用者关心的,因此可以用文本的 md5 编码做为文件名,实现不同的文本对应不同的文件,如果已经生成了对应的文件,无需重复生成,直接返回即可,其中文本转语音,我这里使用的是第三方库 `pyttsx3`[2],使用前 pip install pyttsx3 一下,需要注意的是 Linux 或 Mac 需要安装好 ffmpeg 模块。

text_to_voice 主要代码如下:

# 文件名 text2voice.py
import pyttsx3
from pathlib import Path
import hashlibdef text_to_voice(text: str, is_man: bool = False) -> str:assert text and text.replace(' ',''), "文本不能为空"filename = hashlib.md5(text.encode()).hexdigest() + ".mp3"filepath = Path('voices') / Path(filename)if filepath.exists():return filenameengine = pyttsx3.init()  # object creationengine.save_to_file(text, filepath.as_posix())engine.runAndWait()engine.stop()return filenameif __name__ == '__main__':path = text_to_voice("Python七号,每天学习一个 Python 技巧")print(path)

现在一个文本转语音的程序已经好了,万事具备,只欠 FastAPI 了。

2、将函数转化为 Web API

如果你是第一次使用 FastAPI,请先阅读一下官方文档 https://fastapi.tiangolo.com/[3],至少把用户指引部分看一遍:

然后,你就可以很轻松地将第 1 步中的函数转换成对应的 Web API:

from text2voice import text_to_voice
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from starlette.responses import FileResponse
from pathlib import Pathapp = FastAPI()@app.get("/text2voice/")
def convert_text_to_voice(text: str):filename = text_to_voice(text)return {"filename": filename}@app.get("/download/{filename}")
def download_file(filename:str):file_path = Path('voices') / Path(filename)return FileResponse(file_path.as_posix(), filename=filename)

以上文件保存为 api.py,命令行执行 uvicorn api:app --host 0.0.0.0 --port 8000 --reload 即可启动 8000 端口上的 http 服务。

现在浏览器访问 http://localhost:8000/docs,就可以对这两个接口进行测试了。

3、写个前端界面

如果你不满足于接口开发,可以自己写个前端界面来玩一玩,前端,我推荐 Vue,其他的没时间就不用学了,这个够用了。使用 Vue 前先安装 Node.js, 这个就不说了。

使用 Vue 前请先在 Vue 的官方网站 https://cn.vuejs.org/index.html[4] 学习 Vue 的生命周期,语法,条件渲染,组件化等知识。

第一步:安装 Vue 脚手架。

npm install -g @vue/cli
# OR
yarn global add @vue/cli

可以执行 vue --version 进行验证:

(py38env) ➜  ~ vue --version
@vue/cli 4.5.13

第二步:创建一个项目。

执行:

vue create front_end

选择最新 Vue 3

然后等待初始化完成。

第三步:安装依赖。

为了让组件更美观,我这里引入 element-ui,

cd front_end
vue add element-plus

我不在乎那点 js 文件的体积,这里选择全部引入,后面的地区选择 cn 即可。

为了和后端交互,这时使用 axios:

npm install axios

第四步:编写前端 Vue 文件。

front_end/src/components 目录下新建一个 Text2Voice.vue

文件内容如下:

<template><div class="hello"><h1>文本转语音</h1><el-inputtype="textarea":rows="3"placeholder="请输入文本内容"style="width:500px;"v-model="textarea"></el-input><div style="padding-top:20px"><el-button type="primary" @click="onConvert">转语音</el-button></div><div v-if="convert" style="padding-top:20px"><label>转换结果,点击下载: </label><br/><el-link type="primary" :href="download_url" >{{voice_name}}</el-link></div></div>
</template><script>
const api = "http://127.0.0.1:8000";
const axios = require('axios');
export default {name: 'Text2Voice',props: {msg: String},data(){return {textarea: '',voice_name: 'xxxx.mp3',download_url: '',convert: false}},methods: {onConvert(){if(this.textarea === ""){this.$message({message: '文本不能为空',type: 'warning'});return;}axios.get(`${api}/text2voice/?text=${this.textarea}`).then( res => {console.log(res);this.voice_name = res.data.filename;    this.download_url =  `${api}/download/${res.data.filename}`;  console.log(this.download_url)this.convert = true;})}}
}
</script>

然后在 App.vue 中将所有的 HelloWorld 替换为 Text2Voice,然后执行 npm run serve,在浏览器中打开 http://localhost:8080/ 可以看这样的界面:

打开浏览器的调试工具 console,然后输入文本测试,发现接口报错:

你遇到了一个所有前后端分离开发都会遇到的问题,就是跨域问题,因为 localhost:8080localhost:8000 是两个不同的域,解决方案有两种,一种是让 Vue 走代理,另一种是让后端开启跨域白名单,这里我用第二种,也就是在文件 api.py 加下白名单,最终的代码如下:


from text2voice import text_to_voice
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from starlette.responses import FileResponse
from pathlib import Path
from fastapi.middleware.cors import CORSMiddlewareapp = FastAPI()origins = ["http://localhost:8080",
]app.add_middleware(CORSMiddleware,allow_origins=origins,allow_credentials=True,allow_methods=["*"],allow_headers=["*"],
)@app.get("/text2voice/")
def convert_text_to_voice(text: str):filename = text_to_voice(text)return {"filename": filename}@app.get("/download/{filename}")
def download_file(filename:str):file_path = Path('voices') / Path(filename)return FileResponse(file_path.as_posix(), filename=filename)app.mount("/", StaticFiles(directory="front_end/dist",html = True), name="static")

至此,你会现在接口可以正常使用了。

第五步:编译。最后,执行 npm run build 编译,会生成 index.html,js,css 等静态资源,然后将 fastapi 的静态资源指向这个目录,对应的代码就是:

app.mount("/", StaticFiles(directory="front_end/dist",html = True), name="static")

打开 http://localhost:8000 就可以访问前端界面,此时不存在跨域问题,关闭跨域白名单也不影响使用。正式部署时可以将接口改成这样:

axios.get(`/text2voice/?text=${this.textarea}`)
.then( res => {console.log(res);this.voice_name = res.data.filename;    this.download_url =  `${api}/download/${res.data.filename}`;  console.log(this.download_url)this.convert = true;
})

4、发布成 Docker 镜像

你写好的东东别人怎么用呢?目前最流行的方式就是发布成 Docker 镜像,使用者无需一步一步处理环境配置,一条 docker run 命令就可以使用你的程序了,非常高效。

api.py 文件同级别的目录中新建文件 Dockerfile,内容如下:

FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7
RUN apt update && apt -y install espeak ffmpeg libespeak1
COPY ./ /app

当然了,为了不让 Docker 镜像过大,我们需要忽略一些不必要的文件,借助 .dockerignore 文件完成,内容如下:

front_end/node_modules
front_end/public
front_end/src
front_end/package.json
front_end/package-lock.json
front_end/babel.config.js
voices
__pycache__
front_end/.DS_Store
/front_end/.git/

在 Dockerfile 的同一级目录执行 docker build -t text2voice . 打包镜像文件。

执行 docker images | grep text2voice 查看一下已经打包好的镜像:

然后启动容器,测试一下:

docker run -d -p 80:80 -e MODULE_NAME="api" -e PORT=80 text2voice

注意:这里的 -e MODULE_NAME="api" -e PORT=80 意思是设置环境变量,表示我们的 FastAPI 的主程序是 api.py,运行在端口 80 上, -p 80:80 表示将容器的 80 端口暴露给宿主机(本机)的 80 端口,现在打开浏览器,输入 http://localhost 看一下效果:

OK,接下来就是发布了。先在 https://hub.docker.com/ 上注册一个账号,并创建一个仓库,比如叫 text2voice。

注意,我们创建的仓库是 text2voice,假如你的账号 id 叫 somenzz,因此先执行docker tag text2voice somenzz/text2voice 给已打包好的镜像再打个标签,然后执行 docker push somenzz/text2voice 就可以上传本地镜像到  https://hub.docker.com。

接下来,别人就可以执行一条命令使用你的程序了,前提是已经安装好 Docker:

docker run -d -p 80:80 -e MODULE_NAME="api" -e PORT=80 somenzz/text2voice

docker 会自动下载镜像,并启动一个容器,别人在浏览器打开 http://localhost 即可访问接口服务。接口文档:http://localhost/docs

最后的话

麻雀最小,五脏俱全。以上涉及的接口开发,前端开发,发布 Docker 等环节,虽然简单,却也展示了 Web 开发的一套流程,如果对你的 Web 开发有所帮助,请在看、点赞支持。

都看到这里了,你确定不关注一下吗?

回复「文本转语音」获取全部源代码。

留言讨论

推荐阅读:

FastAPI框架诞生的缘由(上)

FastAPI框架诞生的缘由(下)

手摸手,带你入门docker

参考资料

[1]

FastAPI: https://fastapi.tiangolo.com/

[2]

pyttsx3: https://github.com/nateshmbhat/pyttsx3

FastAPI:快速开发一个文本转语音的接口相关推荐

  1. 阿里云开发一个文本转语音的网页(Springboot+vue)

    演示视频请点击查看B站视频 数据库文件和源代码请看这里 源代码请点击 0首先你需要有阿里云账号并且开通语音服务 有免费试用详情见官网的步骤开通语音 1页面展示 2前端 因为我是用的人人fast框架搭建 ...

  2. 【如何开发小程序?】如何快速开发一个小程序

    ​ 在过去,对于新手来说,如何开发一个小程序只需要半个月到一个月的时间来制作一个简单的小程序.在中间,您需要了解小程序代码的逻辑语言.您需要查看微信官方平台开发文档中的大量示例和示例.那么现在如何开发 ...

  3. 【FastAPI 03】FastAPI快速搭建一个博客系统

    标题:FastAPI快速搭建一个博客系统 大家好,我是Kuls. 这是<小白学FastAPI>系列的第三篇文章. 今天我们主要讲的是FastAPI快速搭建一个博客系统. 这里可能有些小伙伴 ...

  4. 如何快速开发一个完整的ios直播app

    如何快速开发一个完整的iOS直播app 一.个人见解(直播难与易) 直播难:个人认为要想把直播从零开始做出来,绝对是牛逼中的牛逼,大牛中的大牛,因为直播中运用到的技术难点非常之多,视频/音频处理,图形 ...

  5. 快速开发一个PHP扩展

    快速开发一个PHP扩展 作者:heiyeluren 时间:2008-12-5 博客:http://blog.csdn.net/heiyeshuwu 本文通过非常快速的方式讲解了如何制作一个PHP 5. ...

  6. 使用.NET Core快速开发一个较正规的命令行应用程序

    程序员的世界,命令行工具一直是"体验非常友好"的工具,也能自动化完成很多事情,同时还能结合shell来进行某项任务的批处理(脚本).在.NET Core中,命令行应用程序是基础,但 ...

  7. 有了 serverless,前端也可以快速开发一个 Puppeteer 网页截图服务

    更多云原生技术资讯可关注阿里巴巴云原生技术圈. Puppeteer 是什么? puppeteer 官网的介绍如下: Puppeteer is a Node library which provides ...

  8. 如何快速开发一个 Dubbo 应用?(含沙龙报名)

    阿里妹导读:在分布式系统中,远程调用是最基础也是最重要的基石.历史上,曾经先后出现过 CORBA.RMI.EJB.WebService 等技术和规范,在服务化以及微服务日趋流行的今天,更多的被广泛使用 ...

  9. 如何快速开发一个 Dubbo 应用

    转载自   如何快速开发一个 Dubbo 应用 导读:在分布式系统中,远程调用是最基础也是最重要的基石.历史上,曾经先后出现过 CORBA.RMI.EJB.WebService 等技术和规范,在服务化 ...

最新文章

  1. 从博客园博问站点迁移ASP.NET Core展望.NET Core
  2. .net中close和dispose及关闭流操作
  3. ML之xgboostGBM:基于xgboostGBM算法对HiggsBoson数据集(Kaggle竞赛)训练(两模型性能PK)实现二分类预测
  4. hbase hbck命令示例
  5. ASP.NET TextBox 当鼠标点击后清空默认提示文字
  6. NUnit的使用中可能遇到的问题
  7. 使用ros3d.js实现web 端3D建图
  8. TypeScript:初体验
  9. Python异步高并发批量读取URL链接
  10. maya python window_安装了Anaconda之后,Maya运行报错,Python 找不到 Maya 的 Python 模块...
  11. Typec接口颜色代表什么?
  12. 短进程优先调度算法c语言spf,短进程优先的调度算法详解
  13. 扑克牌游戏----花色从大到小按黑桃(Spade)、红桃(Heart)、梅花(Club)、方块(Diamond)排列
  14. Squid缓存代理服务器
  15. t00ls.net关闭了
  16. Android逆向系列(一):初探Android逆向
  17. 单片机进阶---PCB开发之照葫芦画瓢(一)
  18. python生成word目录_Python 文件与目录操作方法总结
  19. C# 网络爬虫利器之Html Agility Pack如何快速实现解析Html
  20. 类同属性不为null 拷贝赋值

热门文章

  1. html 苹果app安装app,未越狱的苹果手机如何安装非App Store的应用?
  2. Synaptics FP Sensors(WBF)(PID=0011)无法录入Windows Hello问题记录
  3. 网上讲的比较清晰的VOT跟踪评价指标EAO
  4. 图像的上采样(upsampling)与下采样(subsampled)
  5. 跨平台比较工具MELD,BCOMPARE
  6. 名字生成器 php,php生成器对象
  7. 不能正常打开Eclipse闪退的问题
  8. 数据仓库Build The Data Warehouse(William H.Inmon)学习笔记 --- 第六章、分布式数据仓库
  9. 三星 SGH-I900/I908修改生产日期
  10. 如何更改计算机任务栏图标,win7修改任务栏图标|win7系统如何将任务栏图标变大...