1. 程式人生 > >離線語音合成使用——科大訊飛or雲知音or百度語音

離線語音合成使用——科大訊飛or雲知音or百度語音

本片主要講解如果使用科大訊飛和雲知音這兩個離線語音合成功能。

目前語音合成的主要有科大訊飛、百度語音、雲知聲。

一、三大產品功能分析

1.百度語音

百度語音合成只有離線上語音服務(免費),沒有純離線,離線上語音合成,在首次使用語音功能,必須聯網,讓其通過網路獲得百度的授權檔案之後,方可正常使用,之後不聯網也可以正常使用,聯網使用優先使用線上包,不聯網則使用離線包。百度語音合成文件地址:http://ai.baidu.com/docs#/TTS-Android-SDK/top,每天有呼叫次數限制,如下圖:


2.科大訊飛

訊飛語語音合成有線上和離線兩種,線上免費,離線收費,收費標準如下:


線上只有聯網的時候才可以正常使用,離線則無需任何聯網,就可正常使用,如果選擇離線包,體驗版SDk下載後就可以為你生產專用的SDK,SDK的demo中會配置好一切,比如說key這些,都會使用你建應用所給的,無需你手動再進行配置了,簡單易用,但下載下來還得除錯一番方可正常使用。科大訊飛官網:

http://www.xfyun.cn/,SDK文件地址:http://mscdoc.xfyun.cn/android/api/

3.雲知聲

二、三者使用

1.百度語音

如何使用請見文件,文件寫的相當詳細,地址:http://ai.baidu.com/docs#/Begin/top,截圖如下:


包括如何註冊如何使用,都明確標出來了,我只將自己的關於語音合成的程式碼貼出來,如下:

public class BaiDuSpeechUtil {

    private final String TAG = this.getClass().getSimpleName();
    private SpeechSynthesizer mSpeechSynthesizer;
    private String mSampleDirPath;
    private static final String SAMPLE_DIR_NAME = "baiduTTS";
    //-------以下全是在assets下的檔案,使用離線時必須全部copy到手機中方可使用----start--
    private static final String SPEECH_FEMALE_MODEL_NAME = "bd_etts_speech_female.dat";
    private static final String SPEECH_MALE_MODEL_NAME = "bd_etts_speech_male.dat";
    private static final String TEXT_MODEL_NAME = "bd_etts_text.dat";
    private static final String ENGLISH_SPEECH_FEMALE_MODEL_NAME = "bd_etts_speech_female_en.dat";
    private static final String ENGLISH_SPEECH_MALE_MODEL_NAME = "bd_etts_speech_male_en.dat";
    private static final String ENGLISH_TEXT_MODEL_NAME = "bd_etts_text_en.dat";

    //--------end-------------------------------------------------------------


    private static BaiDuSpeechUtil baiDuSpeechUtil = null;
    public static BaiDuSpeechUtil getInstance(){
        if(baiDuSpeechUtil == null) {
            synchronized (BaiDuSpeechUtil.class) {
                if(baiDuSpeechUtil == null) {
                    baiDuSpeechUtil = new BaiDuSpeechUtil();
                }
            }
        }
        return baiDuSpeechUtil;
    }

    /**
     * 初始化百度語音資源
     * @param context
     */
    public void setInitialEnv(Context context) {
        initialEnv(context);
    }
    /**
     * 初始化百度語音播報相關
     * @param context
     */
    public void setInitialTts(Context context, SpeechSynthesizerListener speechSynthesizerListener){
        initialTts(context,speechSynthesizerListener);
    }


    private void initialEnv(Context context) {
//        long start_time= System.currentTimeMillis();
        if (mSampleDirPath == null) {
            String sdcardPath = Environment.getExternalStorageDirectory().toString();
            mSampleDirPath = sdcardPath + "/" + SAMPLE_DIR_NAME;
        }
        makeDir(mSampleDirPath);
        copyFromAssetsToSdcard(context,false, SPEECH_FEMALE_MODEL_NAME, mSampleDirPath + "/" + SPEECH_FEMALE_MODEL_NAME);
        copyFromAssetsToSdcard(context,false, SPEECH_MALE_MODEL_NAME, mSampleDirPath + "/" + SPEECH_MALE_MODEL_NAME);
        copyFromAssetsToSdcard(context,false, TEXT_MODEL_NAME, mSampleDirPath + "/" + TEXT_MODEL_NAME);
        copyFromAssetsToSdcard(context,false, "english/" + ENGLISH_SPEECH_FEMALE_MODEL_NAME, mSampleDirPath + "/"
                + ENGLISH_SPEECH_FEMALE_MODEL_NAME);
        copyFromAssetsToSdcard(context,false, "english/" + ENGLISH_SPEECH_MALE_MODEL_NAME, mSampleDirPath + "/"
                + ENGLISH_SPEECH_MALE_MODEL_NAME);
        copyFromAssetsToSdcard(context,false, "english/" + ENGLISH_TEXT_MODEL_NAME, mSampleDirPath + "/"
                + ENGLISH_TEXT_MODEL_NAME);

//        Log.d(TAG,"initialEnv cost:"+ (System.currentTimeMillis()-start_time));
    }

    private void makeDir(String dirPath) {
        File file = new File(dirPath);
        if (!file.exists()) {
            file.mkdirs();
        }
    }

    /**
     * 將sample工程需要的資原始檔拷貝到SD卡中使用(授權檔案為臨時授權檔案,請註冊正式授權)
     * 主要是在離線時候用到,只需執行一次即可,這裡寫的不嚴謹,應該去判斷一下離線用的那些檔案,sd卡是否存在,如果不存在,則copy,如果存在則無需在copy,可在子執行緒操作
     * @param isCover 是否覆蓋已存在的目標檔案
     * @param source
     * @param dest
     */
    private void copyFromAssetsToSdcard(Context context,boolean isCover, String source, String dest) {
        File file = new File(dest);
        if (isCover || (!isCover && !file.exists())) {
            InputStream is = null;
            FileOutputStream fos = null;
            try {
                is = context.getAssets().open(source);
                String path = dest;
                fos = new FileOutputStream(path);
                byte[] buffer = new byte[1024];
                int size = 0;
                while ((size = is.read(buffer, 0, 1024)) != -1) {
                    fos.write(buffer, 0, size);
                }
                fos.flush();


            } catch (Exception e) {
                e.printStackTrace();
            } finally {

                if (is != null) {
                    try {
                        is.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                }
                if (fos != null) {
                    try {
                        is.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }


            }
        }


    }
//此方法可在子執行緒中操作,由於這個初始化過程比較費時,大概在1s左右,看專案需求而定,如果是進入介面就必須播放(伴隨UI改變的)的,在UI執行緒,如無其他特殊要求,放在子執行緒中即可
    private void initialTts(Context context,SpeechSynthesizerListener speechSynthesizerListener) {
//        long start_time= System.currentTimeMillis();
        mSpeechSynthesizer = SpeechSynthesizer.getInstance();
        mSpeechSynthesizer.setContext(context);
        mSpeechSynthesizer.setSpeechSynthesizerListener(speechSynthesizerListener);
        mSpeechSynthesizer.setApiKey(Constant.APP_KEY_BAIDU, Constant.APP_SECRET_BAIDU);
        mSpeechSynthesizer.setAppId(Constant.APP_ID_BAIDU);

        // 文字模型檔案路徑 (離線引擎使用)
        mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_TEXT_MODEL_FILE, mSampleDirPath + "/"
                + TEXT_MODEL_NAME);
        mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_SPEECH_MODEL_FILE, mSampleDirPath + "/"
                + SPEECH_FEMALE_MODEL_NAME);
        // 本地授權檔案路徑,如未設定將使用預設路徑.設定臨時授權檔案路徑,LICENCE_FILE_NAME請替換成臨時授權檔案的實際路徑,僅在使用臨時license檔案時需要進行設定,如果在[應用管理]中開通了正式離線授權,不需要設定該引數,建議將該行程式碼刪除(離線引擎)
        // 如果合成結果出現臨時授權檔案將要到期的提示,說明使用了臨時授權檔案,請刪除臨時授權即可。

        // 發音人(線上引擎),可用引數為0,1,2,3。。。(伺服器端會動態增加,各值含義參考文件,以文件說明為準。0--普通女聲,1--普通男聲,2--特別男聲,3--情感男聲。。。)
        mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEAKER, "0");
        // 設定Mix模式的合成策略,  //mix模式下,wifi使用線上合成,非wifi使用離線合成)
        mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_MIX_MODE, SpeechSynthesizer.MIX_MODE_HIGH_SPEED_SYNTHESIZE_WIFI);
//        if(SystemUtil.isNetWorkConnected(getCurrentActivity())) {
//            // AuthInfo介面用於測試開發者是否成功申請了線上或者離線授權,如果測試授權成功了,可以刪除AuthInfo部分的程式碼(該介面首次驗證時比較耗時),不會影響正常使用(合成使用時
//            AuthInfo authInfo=this.mSpeechSynthesizer.auth(TtsMode.MIX);
//
//            if (authInfo.isSuccess()){
//                toPrint("auth success");
//            }else{
//                String errorMsg=authInfo.getTtsError().getDetailMessage();
//                toPrint("auth failed errorMsg=" + errorMsg);
//            }
//        }

        // 初始化tts
        mSpeechSynthesizer.initTts(TtsMode.MIX);
        // 載入離線英文資源(提供離線英文合成功能)
        int result = mSpeechSynthesizer.loadEnglishModel(mSampleDirPath + "/" + ENGLISH_TEXT_MODEL_NAME, mSampleDirPath + mSampleDirPath + "/" + ENGLISH_SPEECH_FEMALE_MODEL_NAME);
//        Log.d(TAG,"initialTts cost:"+ (System.currentTimeMillis()-start_time));
    }


    /**
     * 播報的文字
     * @param content
     */
    public  void speakText(String content) {
        try{
            if(mSpeechSynthesizer != null) {
                int result = mSpeechSynthesizer.speak(content);
                if (result < 0) {
                    Log.d(TAG,"error,please look up error code in doc or URL:http://yuyin.baidu.com/docs/tts/122 ");
                }
            }
        }catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 暫停
     */
    public void pauseSpeechSynthesizer(){
        if(mSpeechSynthesizer != null) {
            mSpeechSynthesizer.pause();
        }
    }

    /**
     *  停止播放
     */
    public void stopSpeechSynthesizer(){
        if(mSpeechSynthesizer != null) {
            mSpeechSynthesizer.stop();
        }
    }

    /**
     * 接著停止後的地方播放
     */

    public void resumeSpeechSynthesizer(){
        if(mSpeechSynthesizer != null) {
            mSpeechSynthesizer.resume();
        }
    }

    /**
     *  釋放mSpeechSynthesizer,在使用完之後必須呼叫,確保下個介面使用的時候資源已經釋放掉了,否則下個介面將無法正常播放
     */
    public void releaseSpeechSynthesizer(){
        if(mSpeechSynthesizer != null) {
            mSpeechSynthesizer.release();
        }
    }

    public void setSpeechSynthesizerNull(){
        if(mSpeechSynthesizer != null) {
            mSpeechSynthesizer = null;
        }
    }

    public void endSpeechSynthesizer(){
        pauseSpeechSynthesizer();
        stopSpeechSynthesizer();
        releaseSpeechSynthesizer();
        setSpeechSynthesizerNull();
    }
}

如何呼叫:

public class MeasurePromptActivity extends BaseActivity implements SpeechSynthesizerListener {

    private BaiDuSpeechUtil mBaiDuSpeechUtil;
    private static final String WARM_PROMPT = "百度語音測試,你好開發者";
   
    @Override
    protected void setCurrentContentView() {
        setContentView(R.layout.activity_measure_prompt);
    }

    @Override
    protected void init(Bundle savedInstanceState) {

    }
//   語音初始化及播報
    private void startSpeakText() {
        mBaiDuSpeechUtil = BaiDuSpeechUtil.getInstance();
        mBaiDuSpeechUtil.setInitialEnv(getCurrentActivity());
        mBaiDuSpeechUtil.setInitialTts(getCurrentActivity(), this);

        speakText(WARM_PROMPT);
    }

    private void speakText(String content) {
        if (mBaiDuSpeechUtil != null) {
            mBaiDuSpeechUtil.speakText(content);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        startSpeakText();
    }
//在離開次頁面時呼叫
    private void releaseSpeechSynthesizer() {

        if (mBaiDuSpeechUtil != null) {
            mBaiDuSpeechUtil.releaseSpeechSynthesizer();
        }
    }

    @Override
    public void onSynthesizeStart(String s) {

    }

    @Override
    public void onSynthesizeDataArrived(String s, byte[] bytes, int i) {

    }

    @Override
    public void onSynthesizeFinish(String s) {

    }

    @Override
    public void onSpeechStart(String s) {

    }

    @Override
    public void onSpeechProgressChanged(String s, int i) {

    }

    @Override
    public void onSpeechFinish(String s) {
      
    }

    @Override
    public void onError(String s, SpeechError speechError) {
      
    }
}

以上就是百度語音合成的使用,百度其他使用親自行下載官網提供的sample即可。

2.科大訊飛

科大訊飛線上和離線無非就是配置的問題,這裡我只貼重點程式碼,程式碼都是copy官網提供的sample下的,如下:

/**
	 * 引數設定
	 * @return 
	 */
	private void setParam(){
		// 清空引數
		mTts.setParameter(SpeechConstant.PARAMS, null);
		//設定合成
		if(mEngineType.equals(SpeechConstant.TYPE_CLOUD))
		{
			//設定使用雲端引擎
			mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
			//設定發音人
			mTts.setParameter(SpeechConstant.VOICE_NAME,voicerCloud);
		}else {
			//設定使用本地引擎
			mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL);
			//設定發音人資源路徑
			mTts.setParameter(ResourceUtil.TTS_RES_PATH,getResourcePath());
			//設定發音人
			mTts.setParameter(SpeechConstant.VOICE_NAME,voicerLocal);
		}
		//設定合成語速
		mTts.setParameter(SpeechConstant.SPEED, mSharedPreferences.getString("speed_preference", "50"));
		//設定合成音調
		mTts.setParameter(SpeechConstant.PITCH, mSharedPreferences.getString("pitch_preference", "50"));
		//設定合成音量
		mTts.setParameter(SpeechConstant.VOLUME, mSharedPreferences.getString("volume_preference", "50"));
		//設定播放器音訊流型別
		mTts.setParameter(SpeechConstant.STREAM_TYPE, mSharedPreferences.getString("stream_preference", "3"));
		
		// 設定播放合成音訊打斷音樂播放,預設為true
		mTts.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "true");
		
		// 設定音訊儲存路徑,儲存音訊格式支援pcm、wav,設定路徑為sd卡請注意WRITE_EXTERNAL_STORAGE許可權
		// 注:AUDIO_FORMAT引數語記需要更新版本才能生效
		mTts.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
		mTts.setParameter(SpeechConstant.TTS_AUDIO_PATH, Environment.getExternalStorageDirectory()+"/msc/tts.wav");
	}

回撥監聽,什麼時候開始,什麼時候停止....這些都有的

	 * 合成回撥監聽。
	 */
	private SynthesizerListener mTtsListener = new SynthesizerListener() {
		
		@Override
		public void onSpeakBegin() {
			showTip("開始播放");
		}

		@Override
		public void onSpeakPaused() {
			showTip("暫停播放");
		}

		@Override
		public void onSpeakResumed() {
			showTip("繼續播放");
		}

		@Override
		public void onBufferProgress(int percent, int beginPos, int endPos,
				String info) {
			// 合成進度
			mPercentForBuffering = percent;
			showTip(String.format(getString(R.string.tts_toast_format),
					mPercentForBuffering, mPercentForPlaying));
		}

		@Override
		public void onSpeakProgress(int percent, int beginPos, int endPos) {
			// 播放進度
			mPercentForPlaying = percent;
			showTip(String.format(getString(R.string.tts_toast_format),
					mPercentForBuffering, mPercentForPlaying));
		}

		@Override
		public void onCompleted(SpeechError error) {
			if (error == null) {
				showTip("播放完成");
			} else if (error != null) {
				showTip(error.getPlainDescription(true));
			}
		}

		@Override
		public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
			// 以下程式碼用於獲取與雲端的會話id,當業務出錯時將會話id提供給技術支援人員,可用於查詢會話日誌,定位出錯原因
			// 若使用本地能力,會話id為null
			//	if (SpeechEvent.EVENT_SESSION_ID == eventType) {
			//		String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
			//		Log.d(TAG, "session id =" + sid);
			//	}
		}
	};
切記在結束當前頁面的時候必須將SpeechSynthesizer  mTts 釋放掉
if( null != mTts ){
	mTts.stopSpeaking();
	// 退出時釋放連線
	mTts.destroy();
}

注意:使用時切記一定要配置正確,離線資源播報人必須copy到正確的目錄下,libs的so庫根據需要新增,否則可能導致包體積過大,gradle必須配置正確libs的目錄,否則就會找不見so庫了,報常見的java.lang.UnsatisfiedLinkError錯誤,如下圖



3.雲知聲

雲之聲只介紹離線的,程式碼擷取都是官網的sample中的,用法和百度的類似,如下:

public class TTSOfflineActivity extends Activity {

	private static boolean TTS_PLAY_FLAGE = false;

	private EditText mTTSText;
	private TextView mTextViewTip;
	private TextView mTextViewStatus;
	private Button mTTSPlayBtn;
	private SpeechSynthesizer mTTSPlayer;
	private final String mFrontendModel= "frontend_model";
//	private final String mBackendModel = "backend_lzl";
	private final String mBackendModel = "backend_female";
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_offline_tts);
		getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.status_bar_main);

		mTTSText = (EditText) findViewById(R.id.textViewResult);
		mTextViewStatus = (TextView) findViewById(R.id.textViewStatus);
		mTextViewTip = (TextView) findViewById(R.id.textViewTip);
		mTTSPlayBtn = (Button) findViewById(R.id.recognizer_btn);
		mTTSPlayBtn.setEnabled(false);
		mTTSPlayBtn.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				TTSPlay();
			}
		});


		initialEnv();
		// 初始化本地TTS播報
		initTts();
	}

	/**
	 * 初始化本地離線TTS,sample中判斷了是否將assets中的檔案copy到sd卡中了,正式專案無需此操作,直接copy即可,但注意許可權問題,尤其是高版本
	 */
	private void initTts() {

		// 初始化語音合成物件
		mTTSPlayer = new SpeechSynthesizer(this, Config.appKey, Config.secret);
		// 設定本地合成
		mTTSPlayer.setOption(SpeechConstants.TTS_SERVICE_MODE, SpeechConstants.TTS_SERVICE_MODE_LOCAL);
//		File _FrontendModelFile = new File(mFrontendModel);
//		if (!_FrontendModelFile.exists()) {
//			toastMessage("檔案:" + mFrontendModel + "不存在,請將assets下相關檔案拷貝到SD卡指定目錄!");
//		}
//		File _BackendModelFile = new File(mBackendModel);
//		if (!_BackendModelFile.exists()) {
//			toastMessage("檔案:" + mBackendModel + "不存在,請將assets下相關檔案拷貝到SD卡指定目錄!");
//		}
		// 設定前端模型
		mTTSPlayer.setOption(SpeechConstants.TTS_KEY_FRONTEND_MODEL_PATH, mDirPath+ "/" + mFrontendModel);
		// 設定後端模型
		mTTSPlayer.setOption(SpeechConstants.TTS_KEY_BACKEND_MODEL_PATH, mDirPath + "/" + mBackendModel);
		// 設定回撥監聽
		mTTSPlayer.setTTSListener(new SpeechSynthesizerListener() {

			@Override
			public void onEvent(int type) {
				switch (type) {
					case SpeechConstants.TTS_EVENT_INIT:
						// 初始化成功回撥
						log_i("onInitFinish");
						mTTSPlayBtn.setEnabled(true);
						break;
					case SpeechConstants.TTS_EVENT_SYNTHESIZER_START:
						// 開始合成回撥
						log_i("beginSynthesizer");
						break;
					case SpeechConstants.TTS_EVENT_SYNTHESIZER_END:
						// 合成結束回撥
						log_i("endSynthesizer");
						break;
					case SpeechConstants.TTS_EVENT_BUFFER_BEGIN:
						// 開始快取回撥
						log_i("beginBuffer");
						break;
					case SpeechConstants.TTS_EVENT_BUFFER_READY:
						// 快取完畢回撥
						log_i("bufferReady");
						break;
					case SpeechConstants.TTS_EVENT_PLAYING_START:
						// 開始播放回調
						log_i("onPlayBegin");
						break;
					case SpeechConstants.TTS_EVENT_PLAYING_END:
						// 播放完成回撥
						log_i("onPlayEnd");
						setTTSButtonReady();
						break;
					case SpeechConstants.TTS_EVENT_PAUSE:
						// 暫停回撥
						log_i("pause");
						break;
					case SpeechConstants.TTS_EVENT_RESUME:
						// 恢復回撥
						log_i("resume");
						break;
					case SpeechConstants.TTS_EVENT_STOP:
						// 停止回撥
						log_i("stop");
						break;
					case SpeechConstants.TTS_EVENT_RELEASE:
						// 釋放資源回撥
						log_i("release");
						break;
					default:
						break;
				}

			}

			@Override
			public void onError(int type, String errorMSG) {
				// 語音合成錯誤回撥
				log_i("onError");
				toastMessage(errorMSG);
				setTTSButtonReady();
			}
		});
		// 初始化合成引擎
		mTTSPlayer.init("");
	}

	private void TTSPlay() {
		if (!TTS_PLAY_FLAGE) {
			mTTSPlayer.playText(mTTSText.getText().toString());
			setTTSButtonStop();
		} else {
			mTTSPlayer.stop();
			setTTSButtonReady();
		}

	}

	private void setTTSButtonStop() {
		TTS_PLAY_FLAGE = true;
		mTTSPlayBtn.setText(R.string.stop_tts);
	}

	private void setTTSButtonReady() {
		mTTSPlayBtn.setText(R.string.start_tts);
		TTS_PLAY_FLAGE = false;
	}

	protected void setTipText(String tip) {

		mTextViewTip.setText(tip);
	}

	protected void setStatusText(String status) {

		mTextViewStatus.setText(getString(R.string.lable_status) + "(" + status + ")");
	}

	@Override
	public void onPause() {
		super.onPause();
		// 主動停止識別
		if (mTTSPlayer != null) {
			mTTSPlayer.stop();
		}
	}

	private void log_i(String log) {
		Log.i("demo", log);
	}

	@Override
	protected void onDestroy() {
		// 主動釋放離線引擎
		if (mTTSPlayer != null) {
			mTTSPlayer.release(SpeechConstants.TTS_RELEASE_ENGINE, null);
		}
		super.onDestroy();
	}

	private void toastMessage(String message) {
		Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
	}



	/**
	 * 將assets檔案下的離線資源copy到sd卡,操作同百度的
	 *
	 * @param isCover 是否覆蓋已存在的目標檔案
	 * @param source
	 * @param dest
	 */
	private void copyFromAssetsToSdcard(Context context, boolean isCover, String source, String dest) {
		File file = new File(dest);
		if (isCover || (!isCover && !file.exists())) {
			InputStream is = null;
			FileOutputStream fos = null;
			try {
				is = context.getAssets().open(source);
				String path = dest;
				fos = new FileOutputStream(path);
				byte[] buffer = new byte[1024];
				int size = 0;
				while ((size = is.read(buffer, 0, 1024)) != -1) {
					fos.write(buffer, 0, size);
				}
				fos.flush();


			} catch (Exception e) {
				e.printStackTrace();
			} finally {

				if (is != null) {
					try {
						is.close();
					} catch (Exception e) {
						e.printStackTrace();
					}

				}
				if (fos != null) {
					try {
						is.close();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}


			}
		}


	}

	private void makeDir(String dirPath) {
		File file = new File(dirPath);
		if (!file.exists()) {
			file.mkdirs();
		}
	}

	private String mDirPath = null;
	private void initialEnv(){
		if(mDirPath == null) {
			String sdcardPath = Environment.getExternalStorageDirectory().toString();
			mDirPath = sdcardPath + "/unsound/tts/";
		}

		makeDir(mDirPath);
		copyFromAssetsToSdcard(this,false,mFrontendModel,mDirPath +"/" + mFrontendModel);
		copyFromAssetsToSdcard(this,false,mBackendModel,mDirPath + "/" + mBackendModel);
	}

}

assets下的檔案入下圖所示:


這樣基本就正常使用了,還是主要gradle的配置

總結:三種方案中,百度無離線,離線使用個人覺得訊飛優於雲知音,但奈何價格貴呀;如果是定位網際網路產品的話,百度的還是比較好的,離線上融合使用,主要是免費了,科大訊飛的線上也是不錯的;語音合成播報離線,可能是由於模型訓練問題,對於英文和特殊數字的處理有時候不準確,例如110,分場合使用,有時候讀一百一十,有時候讀一一零,還有離線包對英文的識別不準確,有時候會逐個字母的讀,線上一般不會有問題的,由於大多是網際網路產品,都會聯網的,所以上述問題可以忽略的。

關於上方SDK的使用,個人認為先去研究其demo,先保證下載下來能正常使用,大多數出現最多的問題可能是由於無法正確配置導致的,一般主要有以下兩點:

1.so庫沒放對位置

2.gradle檔案配置錯誤(包括lib/jinLibs的路徑配置,gradle版本等等)

3.AndroidManifest配置錯誤,包括許可權等等

這些問題只要細心點都是可以避免的,如果出現問題仔細閱讀官網的文件,尋找解決方法,如果無法解決可以聯絡其技術幫忙解析

相關推薦

離線語音合成使用——科大or知音or語音

本片主要講解如果使用科大訊飛和雲知音這兩個離線語音合成功能。目前語音合成的主要有科大訊飛、百度語音、雲知聲。一、三大產品功能分析1.百度語音百度語音合成只有離線上語音服務(免費),沒有純離線,離線上語音合成,在首次使用語音功能,必須聯網,讓其通過網路獲得百度的授權檔案之後,方

ROS語音科大參考

百度語音介面:https://blog.csdn.net/u011118482/article/details/55001444科大訊飛:https://www.ncnynl.com/archives/201702/1287.htmlhttps://blog.csdn.net

Cordova外掛(語音識別--科大)

cordova-plugin-IFlyspeech 科大訊飛的語音聽說讀寫的cordova外掛 最近在做一個hybrid webapp的時候需要用到語音識別的功能,網上找到科大訊飛的語音cordova外掛,因為還沒開始使用這個外掛,先總結一下在配置科大

ios下的語音開發——科大使用

科大訊飛是國內做的比較好的語音開發sdk,首先在網站上註冊賬號等一系列流程下來之後,獲得id的值 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictio

為什麼語音科大差了幾條街?

辛辛苦苦,信心滿滿的集成了百度TTS語音合成,結果客戶隨便發了個abcdefghijklmn,分分鐘把百度語音完爆了。 http://ai.baidu.com/tech/speech/tts http://www.xfyun.cn/services/online_tts

C#調用科大離線語音SDK合成TTS

zha http post ref top 代碼 來源 內容 lib bin目錄下有msc.dll動態庫。c#調用科大訊飛的語音合成,需要引用該文件。 該文件是C語言生成的dll,C#沒辦法直接引用。所有需要用C#重新封裝一個TTS.dll,然後再在C#項目中引用封裝的TT

在C#中使用科大Web API進行語音合成

.get 接口 style serialize pan python版本 compute serial try   最近工作中需要用到訊飛語音合成接口,網上看了下基本都是Java,PHP,Python版本的,正好補上C# 版本,代碼比較簡單。    首先在訊飛開放平臺上創

有關整合科大sdk的語音(三)語音合成

有關語音合成的,廢話不說,直接程式碼 @property (nonatomic, strong) IFlySpeechSynthesizer *iFlySpeechSynthesizer;//語音合成 - (void)viewWillAppear:(BOOL)animated

手把手的操作——用java呼叫科大離線語音識別dll實現離線識別(JNA實現)(一)

#用java呼叫科大訊飛的離線語音識別dll實現離線識別(JNA實現)(一) 本人接的任務,做離線語音識別,用的是科大訊飛的離線識別,java不支援離線了,所以下載了windows的離線包,用JNA進行呼叫。之前用的是jni,但是一直沒有測試通過,本人又不會C++,研究了一個星期終究

科大語音使用經歷

科大訊飛的語音識別是屬於一流的行列,那不多想當然選擇科大訊飛了。 在百度上輸:訊飛語音 就能找到,輸科大訊飛會直接出現官網,那裡面沒有。(ps我第一次就是這樣) 下載後會有三個檔案選擇。 一個是語音+  帶有語音+APP的。一個是含語音互動介面,一個是不含語音互

手把手的操作——用java呼叫科大離線語音識別dll實現離線識別(JNA實現)(二)

上一篇講到了最難的地方,引數的轉換,這裡單獨寫出來 ** 三、引數的轉換(難點) ** 注:本文是以訊飛提供的C語言例子作為模板改寫,語音來源於檔案 1、先分析提供的例子 本人使用的是VS2010 下載連結連結:https://pan.baidu.com/s/

ubuntu下,在QT中利用科大語音庫實現語音合成TTS

首先要去科大訊飛語音庫註冊,下載linux下的線上合成TTS的SDK,然後在QT下建立一個基於控制檯的工程,其實建立關於UI的也可以,問題不大,這裡以控制檯工程進行說明。將sample中TTS部分的t

科大離線語音命令詞識別的使用說明

      最近因為專案的需求,需要在無網路的情況下實現語音識別的功能,因為之前線上識別一直用的科大的,所以經理就和我說,你花半天時間簡單熟悉一下,然後出一個Demo,下午有人過來看;因為之前科大線上SR也是別人做的,準確的說我只是瞭解過一點,也寫過相關的blog——百度語音

科大語音合成,pcm轉wav

import android.media.AudioFormat; import android.media.AudioRecord; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.Fi

科大超強的合成語音軟體InterPhonic下載

1、理論上來說是版本越高越好,比如現在科大訊飛網站上的InterPhonic 6.0線上演示、ViViVoice2.0 線上演示 語氣就更自然更流暢。 2、文語通2.0是科大訊飛的早期版本,所以讀的聲音肯定是不如InterPhonic 4.0、5.0的。 [中科大訊飛

android 融 + 科大 實現仿微信語音訊息轉換為文字(附DEMO原始碼)

融雲SDK 使用很方便,簡單配置就可以搭建即時通訊功能,配合科大訊飛的語音識別, 即可實現微信中語音訊息轉換為文字的功能 融雲sdk的基本使用就不細說了, 網上很多資料 使用融雲sdk自帶的聊天會話介面,想要在此會話介面上增加語音訊息長按時彈出 “轉換為文

Android 科大 線上和離線語音聽寫

效果圖: 參考資料 專案裡要用語音聽寫,想到了科大訊飛,參考上面的資料完成了最簡單的線上有UI的語音識別,後面想要改成離線也可以使用。參考下面的文章 下載好語記和離線資源之後,想要改成有UI的RecognizerDialog離線語音聽寫,但是沒

科大語音合成5.0破解版 安裝方法

安裝方法 第一步:建立安裝目錄 在D盤新建兩個資料夾 A和 B做為軟體的安裝目錄 第二步:安裝執行庫 點選InterPhonic5.0執行庫\Runtime Demo資料夾中的Runtime(Demo)_Chinese (PRC).msi 進行安裝 安裝到 第一步時在D

接入高德 SDK 遇到的問題 01:語音導航中科大線上語音合成次數限制

需求:採用高德導航SDK實現路線導航,並且實現語音播報導航 問題:高德導航語音合成開發指南中,建議採用的科大訊飛線上語音合成存在次數限制,遠遠達不到生產環境的需求量 解決:採用百度離線上語音識別 Android SDK 一、科大訊飛語音合成使用次數有限

關於科大語音合成的開發(先寫個本地的,簡單)

1、首先在科大訊飛官網申請應用下載語音合成SDK,在專案中匯入Msc.jar包,別忘了還有armeabi目錄下的檔案。然後建一個語音合成的工具類SpeechUtil_xf,具體程式碼下面貼出來,相信大家看註釋已經很清楚了; package com.chai