1. 程式人生 > >說一說科大訊飛Windows版本喚醒功能10102功能的問題

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