一窟哺、背景
客服的通話錄音需要轉(zhuǎn)成文字,團(tuán)隊(duì)決定使用科大訊飛的語音轉(zhuǎn)文字服務(wù)铺然,使用的是 SDK 的方式進(jìn)行對接俗孝。
二、遇到的坑
1探熔、關(guān)于 SDK 集成的坑
問題:該SDK的集成方式只有一種驹针,即提供一個(gè) jar 包供下載,不提供 maven 倉庫管理诀艰,不提供源碼給予定制柬甥。
2、關(guān)于強(qiáng)制讀取配置文件 的坑
下圖是規(guī)定的名為 config.properties 的配置文件其垄。
在類文件 LfasrClientImp 中苛蒲,有一個(gè)靜態(tài)代碼塊,會(huì)強(qiáng)制讀取名為config.properties 的配置文件绿满,然后校驗(yàn)該配置文件中的屬性是否合法臂外,這個(gè)class文件是我們重點(diǎn)調(diào)整的對象。
而且在初始化的過程中喇颁,只要有不符合初始化要求的邏輯漏健,則會(huì)給該類中的靜態(tài)私有變量 private static String err_msg = null
賦予錯(cuò)誤信息。
該錯(cuò)誤信息很關(guān)鍵橘霎,因?yàn)檫@個(gè)類是整個(gè) SDK 的精華蔫浆,即客戶端的精華,所有的操作都需要先創(chuàng)建這個(gè)類的對象進(jìn)行操作姐叁,然而當(dāng)上文提到的私有變量 error_msg 不為 null 時(shí)瓦盛,構(gòu)造函數(shù)直接報(bào)錯(cuò)洗显,所以導(dǎo)致無法創(chuàng)建對象,整個(gè)業(yè)務(wù)流程就沒法走下去原环,見下圖的構(gòu)造方法挠唆。
3、關(guān)于日志的坑
① 原版SDK的源碼嘱吗,強(qiáng)制使用log4j玄组,所以對于少數(shù)不使用 log4j 的項(xiàng)目,需要進(jìn)行調(diào)整柜与,附上報(bào)錯(cuò)信息:
log4j:WARN No appenders could be found for logger (com.jet.service.XfyunService).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
② 原版 SDK 會(huì)打印很多的日志巧勤,比如有一些對音頻進(jìn)行處理的日志嵌灰,部分日志信息是我們不需要的弄匕。
4、關(guān)于文件上傳的坑
語音文件上傳的模式只有一種沽瞭,即給定一個(gè)本地的音頻路徑迁匠。
而如果你使用過七牛云的 SDK 你就深有體會(huì)訊飛的這個(gè)SDK 是有多爛,七牛云的上傳文件的方法驹溃,你可以提供文件的本地路徑城丧,也支持流上傳,當(dāng)然也支持遠(yuǎn)程文件地址的方式上傳豌鹤。
三亡哄、埋坑史
1、 解決本地jar包的引入
<!-- 科大訊飛語音轉(zhuǎn)文字 SDK -->
<dependency>
<groupId>cn.xfyun</groupId>
<artifactId>raasr</artifactId>
<version>2.0.0.1006</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/lfasr-sdk-client-2.0.0.1006.jar</systemPath>
</dependency>
打jar包的時(shí)候把本地的 jar 包也打進(jìn)去:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.Jet.jetApplication</mainClass>
<executable>true</executable>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
</plugins>
</build>
2布疙、解決配置文件的讀取問題
依著他給個(gè)指定的配置文件 config.properties蚊惯,但是還是按照項(xiàng)目里的一樣,區(qū)分開發(fā)灵临、測試和生產(chǎn)配置文件截型,然后強(qiáng)制讀取本項(xiàng)目的配置,去強(qiáng)制覆蓋 LfasrClientImp 類中的變量儒溉。
3宦焦、解決 LfasrClientImp 類中變量私有化的問題
為什么關(guān)注該類中的靜態(tài)私有變量呢,因?yàn)樯衔闹刑岬接袀€(gè)私有的變量存儲(chǔ)錯(cuò)誤信息顿涣,我們需要調(diào)整這個(gè)錯(cuò)誤信息波闹。
而對于 LfasrClientImp 類中的靜態(tài)私有屬性,我們可以通過反射機(jī)制強(qiáng)制刷新屬性涛碑。
Class<LfasrClientImp> lfasrClientImpClass = LfasrClientImp.class;
Field field = lfasrClientImpClass.getDeclaredField("SERV_APP_ID_VAL");
field.setAccessible(true);
field.set(lfasrClientImpClass, "testAppId");
4精堕、解決日志的坑
訊飛默認(rèn)使用的是 log4j,如果很不幸你的項(xiàng)目使用的不是 log4j锌唾,要么你做出妥協(xié)锄码,要么夺英,就出大絕招:把訊飛 SDK 的 class 文件反編譯出來,然后自己改源碼滋捶,然后兩條路可以走痛悯,一是再編譯成 jar 包,二是直接作為一個(gè) module 來使用重窟。
但是還是建議調(diào)整日志框架為 log4j载萌,不要?jiǎng)?SDK,防止版本更新巡扇。
5扭仁、解決上傳接口的坑
上文提到了關(guān)于上傳的方法,只有一個(gè)厅翔,即提供一個(gè)音頻文件的本地地址乖坠,然后傳給上傳的方法。
what刀闷?難道我的音頻文件不能是遠(yuǎn)程服務(wù)器上的熊泵?對于這種情況,我們需要手動(dòng)進(jìn)行封裝甸昏,如果不想封裝得太深顽分。
簡單的思路就是:下載文件 -> 保存成臨時(shí)文件 -> 調(diào)用方法
public static File downLoadFiles(String Url) {
try {
InputStream in = new URL(Url).openConnection().getInputStream();
if (in == null) return null;
String fileName = storePath + "/" + Url.substring(Url.lastIndexOf("/"));
File file = new File(fileName);
OutputStream os = new FileOutputStream(file);
int bytesRead = 0;
byte[] buffer = new byte[8192];
while ((bytesRead = in.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
in.close();
return file;
} catch (IOException e) {
log.error("inputStream zhuan file 異常", e);
}
return null;
}
四、大絕招
其實(shí) SDK 的底層就是封裝了三樣?xùn)|西施蜜,鑒權(quán)卒蘸、http 請求 和 響應(yīng),我們完全可以通過觀看源碼翻默,找出它的鑒權(quán)等動(dòng)作缸沃,然后自己封裝一套請求,這樣就可以完全脫離訊飛的SDK了冰蘑。
五和泌、備注
附上訊飛 SDK 的 maven 引用: