說一說科大訊飛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文件來喚醒之前設置好的詞彙了。

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