你好,游客 登录
背景:
阅读新闻

语音服务器的选型

[日期:2017-01-09] 来源:  作者: [字体: ]

最近游戏要接入一下语音服务器,调查了一下融合的语音sdk

腾讯云GVoice: https://www.qcloud.com/document/product/556/7673

好像只有这个比较靠谱,但是收费好像有点贵,还是决定基于原有的免费的百度语音识别造一个轮子

选型

要解决几个问题

  • 语音转文字翻译
  • 高效的web服务器
  • 分布式的文件存储
  • 与游戏服务器沟通的消息队列选择

语音转文字翻译

这个真没法自己造轮子,选择了百度的语音服务

语音识别 50000次/日 配额

支持的语音时长上限为60s

local new_timer = ngx.timer.at

local access_token
local refresh_token

function M.timer_refresh_token(resp)
 local expires_in_sec = resp.expires_in - 3600
 expires_in_sec = expires_in_sec < 0 and 1 or expires_in_sec
 --过期前一天刷新token
 new_timer(expires_in_sec,M.refresh_token)
end

function M.gen_token()
 if not access_token then
 local data = { grant_type="client_credentials", client_id = Config.AppKey, client_secret = Config.AppSecret}
 local resp,err = http_util.get_baidu_token(Config.TOKEN_URL, data)
 access_token = resp.access_token
 refresh_token = resp.refresh_token
 M.timer_refresh_token(resp)
 end
end

function M.refresh_token()
 if refresh_token then
 local data = { grant_type="refresh_token", client_id = Config.AppKey, client_secret = Config.AppSecret, refresh_token = refresh_token }
 local resp,err = http_util.get_baidu_token(Config.TOKEN_URL, data)
 access_token = resp.access_token
 refresh_token = resp.refresh_token
 M.timer_refresh_token(resp)
 else
 M.gen_token()
 end
end


function M.translate_voice(voice)
 local len = string.len(voice)
 local base64_str = ngx.encode_base64(voice)
 local data = {cuid = Config.CUID, token= access_token, channel = 1, format = "amr", rate = 8000,
 len = len, speech = base64_str }
 local resp,err = http_util.post_ret_json(Config.VOICE_URL, data)
 if not err then
 local err_no = resp.errno
 if ERR_TBL[err_no] then
 return ERR_TBL[err_no]
 end
 return resp.result[1]
 end
 return err
end

web服务器

所有的结构是在python在 Flask 上构建的,怕运行效率不行想重新写一个.几经比较之后,没有选择比较熟悉的 java 语言和 tornado ,而是选择了 openresty ,主要是基于几点考虑

  • 是否是经过验证的框架
  • 是否是熟悉的开发语言
  • 开发和部署是否简便快捷

openresty 是在 nginx 的基础上嵌入了 lua 的支持,兼备了 Python 快速开发和 Nginx C 模块的高性能

文件存储

前期小规模的文件存储直接单机就可以了.而且语音这种是有时效性的,通过 ttl 过期即可清除,磁盘空间不会无限增长.

但为了做个新的尝试,也调查了一下分布式的小文件存储

最终使用了 seaweedfs go语言编写,简单易用

消息队列

游戏内 auth 和后台 gm 通信中间件使用的 rabbitmq ,为了保持一致性也使用了这个

架构

流程

由玩家发起语音聊天,将语音压缩成amr上传到中心主机nginx上,由nginx反代 seaweedfs 集群完成语音文件的存储,然后将 返回的文件id 加上 内网的集群ip 组合成 语音id将消息信息 push 到 rabbitmq 队列中,游戏服务器作为 mq 的订阅者实时处理队列内容将消息按频道和 语音id 广播给对应的游戏客户端,游戏客户端用 语音id 请求中心主机nginx再从代理的 seaweedfs 集群中取语音文件.整个语音聊天的过程就完成了.

关于百度语音识别部分

百度语音识别api并不支持流式上传数据,而且把识别这部分放到上传语音的过程中加重了 rpc 调用的负担.所以这部分可以放到游戏客户端直接请求百度api

收藏 推荐 打印 | 录入:Cstor | 阅读:
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数
点评:
       
评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款
热门评论