说一说科大讯飞Windows版本唤醒功能10102功能的问题

在使用UE4整合科大讯飞唤醒功能的时候,发现个问题。应该算是科大讯飞唤醒功能代码的不足之处,下面就说一下这个问题。
官方的Demo
按照官网的正常流程下载唤醒SDK,设置唤醒词。然后自己录制一段PCM(内含一再Web上定好的唤醒词汇)。运行,没问题。可以正常唤醒。
自己新建的Win32工程
按照官方的文档设置相关VS配置,运行,也没问题。
UE4工程中的引用
上面第二步的代码完全Copy到UE4自己的工程中,运行。返回错误10102.刚开始2,3天我百思不得其解。找了很多资料,貌似都没有清晰的答案。也在论坛里发了贴询问,很遗憾的是论坛里官方回答是答非所问。
先看看10102错误的官方解释:
这个解释从科大讯飞的角度来看当然没有任何问题。当时如果从开发者的角度来看就有几个问题需要澄清:

第四列是官方给出的解决方案:
1. 检查资源路径是否正确设置
所谓的资源路径是否正确,指的是什么资源?是离线环境下自己录制的PCM还是.jet文件,甚至其它文件。很模糊的解释.很不专业,完全没有从用户的角度来考虑。因为同时我也在使用mysql的库引用。非常顺利,文档解释的很好。通俗易懂。我就在想国内的技术人员重开发,轻文档的日子什么时候才能完结。。这是一件很让人遗憾的事情
2. 检查文件是否可读或者是否损坏
和上面的解释类似,文件指的是那一类文件。文件多了去了,你最起码给划定个范围。当然我这个小项目只有几个可疑文件 .PCM和.jet
我按照官方的解释各种怀疑和修改,没用。依然报10102,后来我仔细调试了几遍代码。发现有可能出问题的地方就是在下面这些代码部分
const char *lgi_param = "appid = xxxxx,engine_start = ivw,ivw_res_path =fo|res/ivw/wakeupresource.jet, work_dir = ."; const char *ssb_param = "ivw_threshold = 0:-20; 1:-20; 2:-20; 3:-20; 4:-20; sst = wakeup"; /* 用户登录 */ ret = MSPLogin(NULL, NULL, lgi_param); //第一个参数是用户名,第二个参数是密码,第三个参数是登录参数,用户名和密码可在http://www.xfyun.cn注册获取 if (MSP_SUCCESS != ret) { printf("MSPLogin failed, error code: %d.\n", ret); goto exit;//登录失败,退出登录 }
准确的说是这两句
const char *lgi_param = "appid = xxxxx,engine_start = ivw,ivw_res_path =fo|res/ivw/wakeupresource.jet, work_dir = ."; const char *ssb_param = "ivw_threshold = 0:-20; 1:-20; 2:-20; 3:-20; 4:-20; sst = wakeup";
因为第二句是设置词汇门槛,只要id和Web上设置的词汇对应即可。所以这一块和10102错误没有理论上的关系。那么排除这句,就剩下第一句了。其实问题就出在了第一句
const char *lgi_param = "appid = xxxxx,engine_start = ivw,ivw_res_path =fo|res/ivw/wakeupresource.jet, work_dir = .";
那么我们就来剖析下这句的几个部分:
appid = xxxx; 只要appid对应Web上建好的应用ID即可,这句不会有错误。排除
engine_start = ivw;启动的是离线唤醒引擎ivw。官方函数说明的设置。也没问题。排除
ivw_res_path =fo|res/ivw/wakeupresource.jet;这句官方函数的说明是设置唤醒引擎的资源原路径 .jet文件中存储了制作好的唤醒词汇以及一些其他东西,因为是二进制,看不到细节。那么我们再分解这句fo|是什么意思?我们看看官方的函数解释:

这个说明中没有给出解释,只是让你按照这样的格式设置就行。甚至还有[offset]这种东西,谁知道你这是什么东西啊,对于这种文档简直让人无语。所以大部分的人只能按照例子这种格式进行设置。那么再看下res/ivw/wakeupresource.jet这句;这句明显就是wakeupresource.jet文件路径关系。事实也是如此,让我们看下官方Demo的文件夹结构截图

上图中的ivw文件夹中存放着wakeupresource.jet文件。那么res/ivw/wakeupresource.jet这句的意思只的就是.jet文件的部分路径关系。看起来没有什么问题。一切都是安排的很妥当。事实上按照官网的配置文档。在win32工程下。确实如此。好,我们暂且放过这句,看下一句
work_dir = . 这一句从字面意思来看指的是工作目录。当然它写个.的意思和cmd中的cd.是一个意思.就是指当前目录。也就是说对於单一的win32工程来说,按照官方文档http://doc.xfyun.cn/msc_windows/412367 做就行了。
那么问题来了,如果自定义项目的可执行文件并不存在于bin目录下。那么work_dir = .这句就应该修改为可执行文件所在的目录,譬如下面这样
work_dir = ../../../../xxx/xxx/xxx/ 这里要说明下work_dir等号后面有个空格。
大家可以看到,从我当前执行文件到访问res/ivw/wakeupresource.jet。需要 ../../../../xxx/xxx/xxx/这么深的目录结构。也就是说设置这个work_dir的目的就是为了能访问到wakeupresource.jet这个文件。这是真正的意义所在。
完整的访问路径其实是work_dir + res/ivw/wakeupresource.jet拼凑起来的。只有这样设置正确,唤醒的时候才能启动唤醒引擎wakeupresource.jet。
上面看似都没问题了,当唤醒引擎启动的时候会在work_dir这个目录下生成一个msc文件夹,里面包含了启动的log和.cfg文件。这都是运行过程中自动产生的。返回结果还是10102.卧槽
这什么几把玩意啊。垃圾SDK。我开始骂了很久,开始怀疑人生。抱怨为啥国内的开发环境如此恶劣。。。等等等。
好吧,说最终的解决办法吧。自己先新建一个msc文件夹。然后将res/ivw/wakeupresource.jet这个文件结构整体copy到其里面。这个新建的msc文件夹的位置位于work_dir 设置的目录后面(注意别搞错,work_dir中并不包含msc/)
当唤醒引擎按照工作目录的设置启动的时候,会在工作目录中生成一个msc,正好覆盖了我们之前新建的msc文件家。然后能顺利的访问msc文件夹下的res/ivw/wakeupresource.jet文件来唤醒之前设置好的词汇了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章