背景
给客户的车间做了一个呼料的系统,大屏幕可以实时显示产线的呼料需求(APP),一方面仓库人员可以手机上看到这些呼料需求,另一方面,仓库的大屏幕可以显示分配到此仓库的呼料需求.
新需求
客户希望有新的呼料请求的时候,大屏幕不仅仅要显示,而且要语音提醒.
因为我们大屏幕用的是 Chrome 的浏览器来显示呼料请求,所以直接使用Chrome 的 TTS 接口即可:
1 | function speakOut(msg) { |
然后其他的逻辑就不写了,比如如何判断新到语音,如何不再播报已经播报过的,如何播报捡料超时的任务等等.
新问题
问题来自我们的大屏幕客户端,原来的硬件结构是 电视机+小主机(插音箱)+Chrome .
现在换成了 树莓派 RespberryPi(插音箱)+电视机+Chromium(Electron 写了个壳子用来保证无人值守)
问题就变成了一连串:
- Chromium在树莓派上貌似没有 TTS 的发音,Google 了一堆,又是加启动参数,又是要装 eSpeak 之类的.全试过没用.具体的表现就是:
window.speechSynthesis.getVoices()
返回的数组是[]
.没有Voice,当然读不出来. - 因为大屏幕终端很多,就算这种方法可行,也不可能一个一个树莓派去调整
- 所以更换思路,准备换成 Web 版本的接口,利用 js 来远程调用播放 MP3
- 找了很多 Web 的接口,貌似都收费…
- 终于,下定决心 自己搭一个TTS语音服务器
首先感谢 http://www.eguidedog.net/cn/ekho.php 的 余音(Ekho) 项目,非常给力.
在服务器上装了Linux发行版.具体的安装教程在:
http://www.eguidedog.net/doc/doc_install_ekho.php 下方 ++CENTOS6安装Ekho的方法++
打算帮他搞一个 Docker 版本的方便自己和大家.放到我的 TODOList 里
具体的安装的时候,还有些小问题,貌似 scl
我没装上, 不过没影响到后续使用.
安装的位置在 : /root/eGuideDog/ekho-8.0
装好之后用 Python 写了个脚本,基于 flask 的,非常简单:
假设以后提供服务的 tts 服务器地址为 tts.todd.com
1 | from flask import Flask, request, jsonify |
注意里面的几个坑:
- 文件太多没有自动清理
- 没有鉴权,不要放出来给别人,容易文件爆炸
- 因为我装ekho的时候,有些路径问题,所以我启动 cmd 之前,加了环境变量.
- nginx 要在前面反向代理:上面大部分不用设置,前三行为了防止 js 调用的时候跨域.第四行用来转给 flask.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20location ~ .*\.mp3{
expires 1s;
access_log off;
}
location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
proxy_pass http://127.0.0.1:5000/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Cookie $http_cookie;
proxy_connect_timeout 600s;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
chunked_transfer_encoding off;
}
其他都不重要.
截至目前 tts 服务器好了.
接下来是前端调用:
把原来的 speakOut函数做一个改造:
1 | function speakOut(msg) { |
其实这里面还有一个大坑,我直接放出来解决方法了,我并没有使用<audio>
标签,
因为我试过,audio
标签在Chrome 的某个版本之后,再也不让自动播放了.
不管你手动调用 play 也好,加上 aotuplay 也罢,都没用.
当然了,手机浏览器很早就这样了,不过手机很简单,用户总得摸手机把,只要他敢摸,咱就有办法让语音放出来,可是电脑不一样啊,这特么大屏幕在仓库的高墙上挂着,总不能让语音来的时候,让仓库的人爬上去点下浏览器吧.
不管咋样,我们这种方法也算解决 Chrome 浏览器 自动播放音频的需求.
总结一下,解决的几个问题:
- CentOS上利用
ekho
+Python Flask
安装 Web 版本的 TTS 语音服务器,可能给公司省了一大笔钱,无以为报,接下来尝试抽空给人家做一个 Docker,顺便给人家Support 一个十块二十块的. - 前端解决 Chrome 浏览器 自动播放音频的问题,在浏览器支持 TTS 时候,调用浏览器接口,不支持的时候,调用 TTS 远程服务器播放 MP3文件.