Android 利用 Voice Search语音接口 进行语音识别结果太不准
生活随笔
收集整理的這篇文章主要介紹了
Android 利用 Voice Search语音接口 进行语音识别结果太不准
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
公司最近在做語音識別的項目,但是又要求要錄音,糾結了很久,后來發現谷歌的借口了,但是去識別不準。唉。。。。直接上代碼大神們幫我看看吧,小弟在此謝過了。
?public class MainActivity extends Activity {/ 日志TAG.private static final String TAG = "MainActivity";// title的文本內容.private TextView yuyinShow;private static String mFileName = null;private static String mNewFileName = null;private static String mshuFileName = null;private static String result;private byte[] head;private byte[] body;private Button btnok, btnCancel, btnSb;// 音頻獲取源private int audioSource = MediaRecorder.AudioSource.MIC;// 設置音頻采樣率,44100是目前的標準,但是某些設備仍然支持22050,16000,11025private static int sampleRateInHz = 44100;// 設置音頻的錄制的聲道CHANNEL_IN_STEREO為雙聲道,CHANNEL_CONFIGURATION_MONO為單聲道private static int channelConfig = AudioFormat.CHANNEL_IN_STEREO;// 音頻數據格式:PCM 16位每個樣本。保證設備支持。PCM 8位每個樣本。不一定能得到設備支持。private static int audioFormat = AudioFormat.ENCODING_PCM_16BIT;// 緩沖區字節大小private int bufferSizeInBytes = 0;private MediaPlayer mPlayer = null;private AudioRecord audioRecord;private boolean isRecord = false;// 設置正在錄制的狀態private ProgressDialog dialog;boolean mStartPlaying = false;boolean playOK = false;String text = "";Handler updateDate = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case 2:btnCancel.setEnabled(true);break;case 3:showOkCircleProgressDialog("識別中", "正在識別請稍等");Toast.makeText(MainActivity.this, "開始網絡了啊!!!",Toast.LENGTH_SHORT).show();yuyinShow.setText("");break;case 4:// startPlaying(mzhuanFileName);break;case 5:closeCircleProgressDialog();Toast.makeText(MainActivity.this, "開始打分嘍!!", Toast.LENGTH_SHORT).show();startPlaying(mshuFileName);yuyinShow.setText(result);break;}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);yuyinShow = (TextView) findViewById(R.id.yuyinShow);btnok = (Button) findViewById(R.id.btn_ok);// btnSb = (Button) findViewById(R.id.btn_ok);mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();mFileName += "/reverseme.pcm";mNewFileName = Environment.getExternalStorageDirectory().getAbsolutePath();mNewFileName += "/reverNew.wav";mshuFileName = Environment.getExternalStorageDirectory().getAbsolutePath();mshuFileName += "/shuNew.wav";// 獲得緩沖區字節大小bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz,channelConfig, audioFormat);// 創建AudioRecord對象btnCancel = (Button) findViewById(R.id.btn_cancel);PackageManager pm = getPackageManager();List<ResolveInfo> list = pm.queryIntentActivities(new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);if (list.size() != 0) {// 語音識別可用btnok.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubif (!isRecord) {btnok.setText("停止錄制");body = null;audioRecord = new AudioRecord(audioSource,sampleRateInHz, channelConfig, audioFormat,bufferSizeInBytes);onRecord(isRecord);} else {btnok.setText("開始錄制");stopRecord();}}});} else {// 語音識別不可用btnok.setEnabled(false);}btnCancel.setEnabled(false);ex_bindListenters();}@Overrideprotected void onActivityResult(int requestCode, int resultCode,Intent intent) {// requestCode 自己傳的代碼// resultCode 返回的結果狀態// TODO Auto-generated method stubif (5 == requestCode && resultCode == RESULT_OK) {Toast.makeText(MainActivity.this, "返回結果正常", Toast.LENGTH_SHORT).show();ArrayList<String> result = intent.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); // 獲取語言的字符String resultString = result.get(0);yuyinShow.setText(resultString);}super.onActivityResult(requestCode, resultCode, intent);}// 當錄音按鈕被click時調用此方法,開始或停止錄音private void onRecord(boolean start) {if (!start) {startRecord();}}// 當播放按鈕被click時調用此方法,開始或停止播放private void onPlay(boolean start) {if (start) {startPlaying(mNewFileName);} else {stopPlaying();}}private void startRecord() {audioRecord.startRecording();// 讓錄制狀態為trueisRecord = true;// 開啟音頻文件寫入線程new Thread(new AudioRecordThread()).start();}private void stopRecord() {close();}private void close() {if (audioRecord != null) {isRecord = false;// 停止文件寫入audioRecord.stop();audioRecord.release();// 釋放資源audioRecord = null;}}class AudioRecordThread implements Runnable {@Overridepublic void run() {writeDateTOFile();// 往文件中寫入裸數據copyWaveFile(mFileName, mNewFileName);// 給裸數據加上頭文件updateDate.sendEmptyMessage(2);}}/*** 這里將數據寫入文件,但是并不能播放,因為AudioRecord獲得的音頻是原始的裸音頻,* 如果需要播放就必須加入一些格式或者編碼的頭信息。但是這樣的好處就是你可以對音頻的 裸數據進行處理,比如你要做一個愛說話的TOM* 貓在這里就進行音頻的處理,然后重新封裝 所以說這樣得到的音頻比較容易做一些音頻的處理。*/private void writeDateTOFile() {// new一個byte數組用來存一些字節數據,大小為緩沖區大小byte[] audiodata = new byte[bufferSizeInBytes];int mPCMSize = 0;FileOutputStream fos = null;int readsize = 0;try {File file = new File(mFileName);if (file.exists()) {file.delete();}fos = new FileOutputStream(file);// 建立一個可存取字節的文件} catch (Exception e) {e.printStackTrace();}while (isRecord == true) {readsize = audioRecord.read(audiodata, 0, bufferSizeInBytes);if (AudioRecord.ERROR_INVALID_OPERATION != readsize) {try {fos.write(audiodata);copybyte(audiodata);} catch (IOException e) {e.printStackTrace();}}}try {fos.close();// 關閉寫入流} catch (IOException e) {e.printStackTrace();}}public void copybyte(byte[] audiodata) {if (body != null) {byte[] c = new byte[body.length + audiodata.length];System.arraycopy(body, 0, c, 0, body.length);System.arraycopy(audiodata, 0, c, body.length, audiodata.length);body = c;Log.i(TAG, "" + body.length);} else {body = audiodata;}}// public void writeDateshengyi(byte[] audiodata) {// FileOutputStream fos = null;// int readsize = 0;// try {// File file = new File(mzhuanFileName);// if (file.exists()) {// file.delete();// }// fos = new FileOutputStream(file);// 建立一個可存取字節的文件//// fos.write(audiodata);//// fos.close();// 關閉寫入流// updateDate.sendEmptyMessage(4);// } catch (IOException e) {// e.printStackTrace();// }// }// 這里得到可播放的音頻文件public void copyWaveFile(String inFilename, String outFilename) {FileInputStream in = null;FileOutputStream out = null;long totalAudioLen = 0;long totalDataLen = totalAudioLen + 36;long longSampleRate = sampleRateInHz;int channels = 2;long byteRate = 16 * sampleRateInHz * channels / 8;byte[] data = new byte[bufferSizeInBytes];try {in = new FileInputStream(inFilename);out = new FileOutputStream(outFilename);totalAudioLen = in.getChannel().size();totalDataLen = totalAudioLen + 36;util.WriteWaveFileHeader(out, totalAudioLen, totalDataLen,longSampleRate, channels, byteRate);while (in.read(data) != -1) {out.write(data);}in.close();out.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}private void startPlaying(String mNewFileName) {mPlayer = new MediaPlayer();try {// 設置要播放的文件mPlayer.setDataSource(mNewFileName);mPlayer.prepare();// 播放之mPlayer.start();} catch (IOException e) {}}// 停止播放private void stopPlaying() {mPlayer.release();mPlayer = null;}private void postHttpURLConnection() {if (head == null && body == null) {} else {
// byte[] mVoiceData = util.getThreeArray(head, body);new Thread(new PostDateThread()).start();}}class PostDateThread implements Runnable {
// byte[] mVoiceData;
//
// PostDateThread(byte[] mVoiceData) {
// this.mVoiceData = mVoiceData;
// }@Overridepublic void run() {try {// writeDateshengyi(mVoiceData);URL httpUrl = null;httpUrl = new URL("http://www.google.com.hk/speech-api/v1/recognize?xjerr=1&client=chromium&lang=zh-CN&maxresults=1");HttpURLConnection urlConnection = null;urlConnection = (HttpURLConnection) httpUrl.openConnection();urlConnection.setConnectTimeout(7000);urlConnection.setReadTimeout(10000);urlConnection.setDoOutput(true);urlConnection.setDoInput(true);urlConnection.setRequestMethod("POST");urlConnection.setUseCaches(false);// urlConnection.setAllowUserInteraction(true);urlConnection.setInstanceFollowRedirects(true);urlConnection.setRequestProperty("User-Agent", "Mozilla/5.0");urlConnection.setRequestProperty("Content-Type","audio/L16; rate=16000");// urlConnection.setRequestProperty("Connection", "Keep-Alive");DataOutputStream writer = new DataOutputStream(urlConnection.getOutputStream());writer.write(util.readfileByYte(mNewFileName));writer.flush();writer.close();FileOutputStream out = null;out = new FileOutputStream(mshuFileName);out.write(util.readfileByYte(mNewFileName));out.close();// FileInputStream input = new FileInputStream();
// byte[] buffer = new byte[bufferSizeInBytes]; //
// 必須用戶自己創建一個buffer。
// int read = input.read(buffer);
// while (read != -1) // 判斷文件讀完的條件
// {
// writer.write(buffer, 0, read);
// read = input.read(buffer);
// }
// writer.flush();
// writer.close();
// input.close();result = "";updateDate.sendEmptyMessage(3);if (urlConnection.getResponseCode() == 200) {// 為輸出創建BufferReaderString inputLine = null;// 得到讀取的內容InputStreamReader reder = new InputStreamReader(urlConnection.getInputStream(), "utf-8");BufferedReader breader = new BufferedReader(reder);// 使用循環來讀取獲得的數據while ((inputLine = breader.readLine()) != null) {// // 我們在每一行后面加\nresult += inputLine + "\n";JSONObject jsonObject = new JSONObject(inputLine);JSONArray jsonArray = jsonObject.optJSONArray("hypotheses");jsonObject = jsonArray.optJSONObject(0);if (jsonObject != null) {result = jsonObject.optString("utterance","對不起未能識別您的語音請重試!");} else {result = "對不起未能識別您的語音請重試!";}updateDate.sendEmptyMessage(5);}Log.i(TAG, result);}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}private void ex_bindListenters() {btnCancel.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stub// onPlay(mStartPlaying);if (mStartPlaying) {postHttpURLConnection();btnCancel.setText("停止播放");} else {btnCancel.setText("播放錄音");}mStartPlaying = !mStartPlaying;}});}public ProgressDialog showOkCircleProgressDialog(String title, String msg) {if (dialog != null) {try {dialog.cancel();dialog = null;} catch (Exception e) {}}dialog = new ProgressDialog(this);dialog.setIndeterminate(false);dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);dialog.setTitle(title);dialog.setMessage(msg);try {dialog.show();Log.e("iitalk", "顯示等待框了啊??");} catch (Exception e) {dialog = null;}return dialog;}// // 關閉加載對話框public void closeCircleProgressDialog() {if (dialog != null) {try {dialog.cancel();Log.e("iitalk", "關閉等待框了啊??");dialog = null;} catch (Exception e) {}}}
}
public class util {/*** 這里提供一個頭信息。插入這些信息就可以得到可以播放的文件。 為我為啥插入這44個字節,這個還真沒深入研究,不過你隨便打開一個wav* 音頻的文件,可以發現前面的頭文件可以說基本一樣哦。每種格式的文件都有 自己特有的頭文件。*/public static File readFlacByByte(String fileName) {File file = new File(fileName);InputStream input = null;try { // System.out.println("yi字節的方式讀取文件");input = new FileInputStream(file) ; // int tempByte = 0; // while ((tempByte = input.read())!= -1) {System.out.println(tempByte); // // }input.close();} catch (Exception e) {e.printStackTrace();return null;// TODO: handle exception}return file;}public static byte[] readfileByYte(String filename) throws IOException {File file = readFlacByByte(filename);long len = file.length();byte[] voice = new byte[(int) len];FileInputStream fileInputStream = new FileInputStream(file);fileInputStream.read(voice, 0, (int)len);fileInputStream.close();return voice;}public static byte[] getThreeArray(byte[] head, byte[] body) {if (body != null) {byte[] c = new byte[head.length + body.length];System.arraycopy(head, 0, c, 0, head.length);System.arraycopy(body, 0, c, head.length, body.length);return c;} else {return head;}}public static void WriteWaveFileHeader(FileOutputStream out, long totalAudioLen, long totalDataLen, long longSampleRate, int channels, long byteRate) throws IOException { byte[] header = new byte[44]; header[0] = 'R'; // RIFF/WAVE header header[1] = 'I'; header[2] = 'F'; header[3] = 'F'; header[4] = (byte) (totalDataLen & 0xff); header[5] = (byte) ((totalDataLen >> 8) & 0xff); header[6] = (byte) ((totalDataLen >> 16) & 0xff); header[7] = (byte) ((totalDataLen >> 24) & 0xff); header[8] = 'W'; header[9] = 'A'; header[10] = 'V'; header[11] = 'E'; header[12] = 'f'; // 'fmt ' chunk header[13] = 'm'; header[14] = 't'; header[15] = ' '; header[16] = 16; // 4 bytes: size of 'fmt ' chunk header[17] = 0; header[18] = 0; header[19] = 0; header[20] = 1; // format = 1 header[21] = 0; header[22] = (byte) channels; header[23] = 0; header[24] = (byte) (longSampleRate & 0xff); header[25] = (byte) ((longSampleRate >> 8) & 0xff); header[26] = (byte) ((longSampleRate >> 16) & 0xff); header[27] = (byte) ((longSampleRate >> 24) & 0xff); header[28] = (byte) (byteRate & 0xff); header[29] = (byte) ((byteRate >> 8) & 0xff); header[30] = (byte) ((byteRate >> 16) & 0xff); header[31] = (byte) ((byteRate >> 24) & 0xff); header[32] = (byte) (2 * 16 / 8); // block align header[33] = 0; header[34] = 16; // bits per sample header[35] = 0; header[36] = 'd'; header[37] = 'a'; header[38] = 't'; header[39] = 'a'; header[40] = (byte) (totalAudioLen & 0xff); header[41] = (byte) ((totalAudioLen >> 8) & 0xff); header[42] = (byte) ((totalAudioLen >> 16) & 0xff); header[43] = (byte) ((totalAudioLen >> 24) & 0xff); out.write(header, 0, 44); } }
public class util {/*** 這里提供一個頭信息。插入這些信息就可以得到可以播放的文件。 為我為啥插入這44個字節,這個還真沒深入研究,不過你隨便打開一個wav* 音頻的文件,可以發現前面的頭文件可以說基本一樣哦。每種格式的文件都有 自己特有的頭文件。*/public static File readFlacByByte(String fileName) {File file = new File(fileName);InputStream input = null;try { // System.out.println("yi字節的方式讀取文件");input = new FileInputStream(file) ; // int tempByte = 0; // while ((tempByte = input.read())!= -1) {System.out.println(tempByte); // // }input.close();} catch (Exception e) {e.printStackTrace();return null;// TODO: handle exception}return file;}public static byte[] readfileByYte(String filename) throws IOException {File file = readFlacByByte(filename);long len = file.length();byte[] voice = new byte[(int) len];FileInputStream fileInputStream = new FileInputStream(file);fileInputStream.read(voice, 0, (int)len);fileInputStream.close();return voice;}public static byte[] getThreeArray(byte[] head, byte[] body) {if (body != null) {byte[] c = new byte[head.length + body.length];System.arraycopy(head, 0, c, 0, head.length);System.arraycopy(body, 0, c, head.length, body.length);return c;} else {return head;}}public static void WriteWaveFileHeader(FileOutputStream out, long totalAudioLen, long totalDataLen, long longSampleRate, int channels, long byteRate) throws IOException { byte[] header = new byte[44]; header[0] = 'R'; // RIFF/WAVE header header[1] = 'I'; header[2] = 'F'; header[3] = 'F'; header[4] = (byte) (totalDataLen & 0xff); header[5] = (byte) ((totalDataLen >> 8) & 0xff); header[6] = (byte) ((totalDataLen >> 16) & 0xff); header[7] = (byte) ((totalDataLen >> 24) & 0xff); header[8] = 'W'; header[9] = 'A'; header[10] = 'V'; header[11] = 'E'; header[12] = 'f'; // 'fmt ' chunk header[13] = 'm'; header[14] = 't'; header[15] = ' '; header[16] = 16; // 4 bytes: size of 'fmt ' chunk header[17] = 0; header[18] = 0; header[19] = 0; header[20] = 1; // format = 1 header[21] = 0; header[22] = (byte) channels; header[23] = 0; header[24] = (byte) (longSampleRate & 0xff); header[25] = (byte) ((longSampleRate >> 8) & 0xff); header[26] = (byte) ((longSampleRate >> 16) & 0xff); header[27] = (byte) ((longSampleRate >> 24) & 0xff); header[28] = (byte) (byteRate & 0xff); header[29] = (byte) ((byteRate >> 8) & 0xff); header[30] = (byte) ((byteRate >> 16) & 0xff); header[31] = (byte) ((byteRate >> 24) & 0xff); header[32] = (byte) (2 * 16 / 8); // block align header[33] = 0; header[34] = 16; // bits per sample header[35] = 0; header[36] = 'd'; header[37] = 'a'; header[38] = 't'; header[39] = 'a'; header[40] = (byte) (totalAudioLen & 0xff); header[41] = (byte) ((totalAudioLen >> 8) & 0xff); header[42] = (byte) ((totalAudioLen >> 16) & 0xff); header[43] = (byte) ((totalAudioLen >> 24) & 0xff); out.write(header, 0, 44); } }
總結
以上是生活随笔為你收集整理的Android 利用 Voice Search语音接口 进行语音识别结果太不准的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: U盘文件损坏怎么恢复
- 下一篇: Android加载网页JavaScrip