注:本文最后更新時(shí)間:2018/08/26,測(cè)試環(huán)境切換為 macOS
測(cè)試環(huán)境
Android Studio 3.1.4
macOS 10.13.6
測(cè)試訊飛語(yǔ)音的 語(yǔ)音聽(tīng)寫(xiě)
和 在線語(yǔ)音合成
功能萌抵,使用訊飛默認(rèn) UI祠够。
下載訊飛 SDK
去科大訊飛開(kāi)發(fā)平臺(tái)下載 相關(guān)的SDK怠益。
解壓后的文件目錄如下:
Android_xxx_xxx_xxxxxx
|-- assets // 訊飛語(yǔ)音的資源文件夾
|-- doc // 開(kāi)發(fā)文檔說(shuō)明
|-- libs // 核心 SDK 文件
|-- arm64-v8a // 下面是幾個(gè)不同CPU架構(gòu)下的平臺(tái)兼容庫(kù)
|-- libmsc.so
|-- armeabi
|-- ...
|-- Msc.jar // 訊飛開(kāi)發(fā)庫(kù)
|-- Sunflower.jar // 使用訊飛語(yǔ)音統(tǒng)計(jì)功能用到的庫(kù)
|-- sample
|-- SpeechDemo
|-- ...
|-- readme.txt
|-- release.txt
導(dǎo)入訊飛 SDK
- 使用 Android Studio 新建一個(gè) Android 工程摹量,為了方便勃痴,我在這里所有設(shè)置均為默認(rèn)季春。
- 將工程視圖切換至 Project 結(jié)構(gòu)洗搂,然后將訊飛文檔中對(duì)應(yīng)的文件夾復(fù)制到 Android 中,如沒(méi)有相應(yīng)的文件夾則需要手動(dòng)新建载弄,具體如下:
訊飛文檔 | Android 工程 |
---|---|
/assets | /app/src/main/assets/ |
/libs/ | /app/libs |
此時(shí)耘拇,查看 /app/build.gradle,確保會(huì)多出下面一行:
buildTypes {
...
}
// 下面這一行 需要手動(dòng)添加侦锯,以加載 .so 動(dòng)態(tài)庫(kù)及其他第三方庫(kù)
sourceSets {
main {
jniLibs.srcDirs = ["libs"]
}
}
為使 /libs/xxx/libmsc.so 文件生效驼鞭,需要在 /gradle.properties 中加入下面一行(為什么?):
# 更新尺碰,新版 AS 貌似可以不加入這一行了挣棕。
android.useDeprecatedNdk = true
- 在
AndroidManifest.xml
中添加相關(guān)權(quán)限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!--讀取網(wǎng)絡(luò)信息狀態(tài) -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--獲取當(dāng)前wifi狀態(tài) -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<!--允許程序改變網(wǎng)絡(luò)連接狀態(tài) -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<!--讀取手機(jī)信息權(quán)限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<application ...>
...
</application>
測(cè)試訊飛 SDK
我們?cè)谥黜?yè)面中加入一個(gè) textView 和 button,點(diǎn)擊 button 則會(huì)開(kāi)始語(yǔ)音聽(tīng)寫(xiě)亲桥,同時(shí)會(huì)將聽(tīng)寫(xiě)結(jié)果顯示到 textView 中洛心,非常簡(jiǎn)單。
activity_main.xml
代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
tools:layout_constraintTop_creator="1"
tools:layout_constraintRight_creator="1"
tools:layout_constraintBottom_creator="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
tools:layout_constraintLeft_creator="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
tools:layout_constraintTop_creator="1"
tools:layout_constraintRight_creator="1"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginTop="20dp"
app:layout_constraintTop_toBottomOf="@+id/textView"
tools:layout_constraintLeft_creator="1"
app:layout_constraintLeft_toLeftOf="parent" />
</android.support.constraint.ConstraintLayout>
MainActivity.java
代碼如下:
package com.example.cn_pa.myapplication;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.cloud.SpeechUtility;
import com.iflytek.cloud.ui.RecognizerDialog;
import com.iflytek.cloud.ui.RecognizerDialogListener;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;
public class MainActivity extends AppCompatActivity {
private SpeechRecognizer mIat;
private RecognizerDialog mIatDialog;
private RecognizerDialogListener mRListener;
private Button button;
private TextView tv;
private String result;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SpeechUtility.createUtility(MainActivity.this, SpeechConstant.APPID +"=XXXXXX"); // 這里要替換成自己申請(qǐng)的 AppID
mRListener = new RecognizerDialogListener() {
@Override
public void onResult(RecognizerResult results, boolean isLast) {
String text = parseIatResult(results.getResultString());
result += text;
tv.setText(result);
if (isLast) {
result = "";
}
}
@Override
public void onError(SpeechError speechError) {
}
};
mIatDialog = new RecognizerDialog(MainActivity.this, null);
mIatDialog.setListener(mRListener);
button = (Button)findViewById(R.id.button);
tv = (TextView)findViewById(R.id.textView);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
setIatParam("zph");
mIatDialog.show();
}
});
}
private void setIatParam(String filename) {
// 清空參數(shù)
mIatDialog.setParameter(SpeechConstant.PARAMS, null);
// 設(shè)置聽(tīng)寫(xiě)引擎
mIatDialog.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
// 設(shè)置返回結(jié)果格式
mIatDialog.setParameter(SpeechConstant.RESULT_TYPE, "json");
// 設(shè)置語(yǔ)言
mIatDialog.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
// 設(shè)置語(yǔ)言區(qū)域
mIatDialog.setParameter(SpeechConstant.ACCENT, "mandarin");
// 設(shè)置語(yǔ)音前端點(diǎn):靜音超時(shí)時(shí)間题篷,即用戶多長(zhǎng)時(shí)間不說(shuō)話則當(dāng)做超時(shí)處理
mIatDialog.setParameter(SpeechConstant.VAD_BOS, "4000");
// 設(shè)置語(yǔ)音后端點(diǎn):后端點(diǎn)靜音檢測(cè)時(shí)間词身,即用戶停止說(shuō)話多長(zhǎng)時(shí)間內(nèi)即認(rèn)為不再輸入, 自動(dòng)停止錄音
mIatDialog.setParameter(SpeechConstant.VAD_EOS, "2000");
// 設(shè)置標(biāo)點(diǎn)符號(hào),設(shè)置為"0"返回結(jié)果無(wú)標(biāo)點(diǎn),設(shè)置為"1"返回結(jié)果有標(biāo)點(diǎn)
mIatDialog.setParameter(SpeechConstant.ASR_PTT, "1");
// 設(shè)置音頻保存路徑番枚,保存音頻格式支持pcm法严、wav,設(shè)置路徑為sd卡請(qǐng)注意WRITE_EXTERNAL_STORAGE權(quán)限
// 注:AUDIO_FORMAT參數(shù)語(yǔ)記需要更新版本才能生效
mIatDialog.setParameter(SpeechConstant.AUDIO_FORMAT,"wav");
mIatDialog.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory() + "/MyApplication/" + filename + ".wav");
}
public static String parseIatResult(String json) {
StringBuffer ret = new StringBuffer();
try {
JSONTokener tokener = new JSONTokener(json);
JSONObject joResult = new JSONObject(tokener);
JSONArray words = joResult.getJSONArray("ws");
for (int i = 0; i < words.length(); i++) {
// 轉(zhuǎn)寫(xiě)結(jié)果詞葫笼,默認(rèn)使用第一個(gè)結(jié)果
JSONArray items = words.getJSONObject(i).getJSONArray("cw");
JSONObject obj = items.getJSONObject(0);
ret.append(obj.getString("w"));
}
} catch (Exception e) {
e.printStackTrace();
}
return ret.toString();
}
}
以上代碼很粗糙深啤,但完成了基本功能演示, 希望對(duì)你有所幫助 :)