一,jsp 網頁使用JavaScript來實現文字轉語音即TTS,TEXT TO speach, javascript
好比: php
仍是微軟官方的方便簡單,否則文字轉語音在網頁上播報這種功能真就麻煩了,特別是漢字轉語音播報。這是使用js來實現的。 html
其次,經過Java實現中文到英文朗讀出來 java
code: android
import java.awt.Container; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.DefaultComboBoxModel; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.JSlider; import javax.swing.JTextArea; import javax.swing.UIManager; import org.loon.framework.jtts.Engine;
import org.loon.framework.jtts.JTTS; public class TalkerTest extends JPanel implements ActionListener { private static final long serialVersionUID = 1L; private JTTS jtts; private JButton jButton1; private JButton jButton2; private JComboBox jComboBox1; private JLabel jLabel1; private JLabel jLabel2; private JLabel jLabel3; private JLabel jLabel4; private JScrollPane jScrollPane1; private JSeparator jSeparator1; private JSlider jSlider1; private JSlider jSlider2; private JTextArea jTextArea1; @SuppressWarnings("unchecked") public TalkerTest() { this.jtts = Engine.getTTS(); this.jSlider1 = new JSlider(); this.jSlider2 = new JSlider(); this.jComboBox1 = new JComboBox(); this.jLabel1 = new JLabel(); this.jLabel2 = new JLabel(); this.jLabel3 = new JLabel(); this.jSeparator1 = new JSeparator(); this.jButton1 = new JButton(); this.jButton2 = new JButton(); this.jScrollPane1 = new JScrollPane(); this.jTextArea1 = new JTextArea(); this.jLabel4 = new JLabel(); setLayout(null); this.jSlider1.setName("jSlider1"); this.jSlider1.setMaximum(500); this.jSlider1.setValue(150); this.jSlider1.setMinimum(0); add(this.jSlider1); this.jSlider1.setBounds(94, 131, 316, 24);
this.jSlider2.setName("jSlider2"); this.jSlider2.setMaximum(200); this.jSlider2.setValue(100); this.jSlider2.setMinimum(0); add(this.jSlider2); this.jSlider2.setBounds(94, 170, 316, 24); String[] types = new String[12]; for (int i = 0; i < types.length; i++) { if (i < 5) types[i] = ("zh+m" + (i + 1)); else { types[i] = ("zh+f" + (i - 4)); } } types[10] = "zh+whisper";
types[11] = "zh+croak";
this.jtts.setLanguage("zh");
this.jComboBox1.setModel(new DefaultComboBoxModel(types));
this.jComboBox1.setName("jComboBox1"); add(this.jComboBox1);
this.jComboBox1.setBounds(100, 210, 100, 23);
this.jComboBox1.addActionListener(this);
this.jLabel1.setText("朗讀間隔:");
this.jLabel1.setName("jLabel1");
add(this.jLabel1);
this.jLabel1.setBounds(20, 125, 66, 30);
this.jLabel2.setText("朗讀音量:");
this.jLabel2.setName("jLabel2");
add(this.jLabel2);
this.jLabel2.setBounds(20, 165, 70, 30);
this.jLabel3.setText("發音規則:");
this.jLabel3.setName("jLabel3"); add(this.jLabel3);
this.jLabel3.setBounds(20, 216, 80, 15);
this.jLabel4.setText("目標文本:");
this.jLabel4.setName("jLabel4");
add(this.jLabel4);
this.jLabel4.setBounds(20, 10, 70, 20);
this.jSeparator1.setName("jSeparator1");
add(this.jSeparator1);
this.jSeparator1.setBounds(10, 268, 398, 10);
this.jButton1.setText("朗讀文本");
this.jButton1.setName("jButton2");
add(this.jButton1);
this.jButton1.setBounds(232, 284, 83, 25);
this.jButton1.addActionListener(this);
this.jButton2.setText("退出應用");
this.jButton2.setName("jButton3");
add(this.jButton2);
this.jButton2.setBounds(325, 284, 83, 25);
this.jButton2.addActionListener(this);
this.jScrollPane1.setName("jScrollPane1");
this.jTextArea1.setColumns(20);
this.jTextArea1.setRows(5);
this.jTextArea1.setName("jTextArea1");
this.jTextArea1
.setText("Hello Java!Hello World!\n史無前例啊,中國踢韓國三比零啦!\n生意興隆,財源廣進,萬事如意,虎年大吉!");
this.jScrollPane1.setViewportView(this.jTextArea1); add(this.jScrollPane1);
this.jScrollPane1.setBounds(98, 10, 310, 106);
} public void actionPerformed(ActionEvent e) { Object source = e.getSource(); if ((source instanceof JButton)) { if (source == this.jButton1) { this.jtts.setRate(this.jSlider1.getValue()); this.jtts.setVolume(this.jSlider2.getValue()); this.jtts.speak(this.jTextArea1.getText().trim()); } if (source == this.jButton2) System.exit(0); } else if ((source instanceof JComboBox)) {
this.jtts.setLanguage(this.jComboBox1.getSelectedItem().toString() .trim()); } } public static void createGUI() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception localException) { }
JFrame frame = new JFrame("Java版TTS組件發音測試(eSpeak封裝)"); frame.setDefaultCloseOperation(3); frame.getContentPane().add(new TalkerTest()); frame.pack(); frame.setSize(new Dimension(420, 345)); frame.setResizable(false); frame.setLocationRelativeTo(null); frame.setVisible(true); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { TalkerTest.createGUI();
} }); }}
圖: web
二,經過 編程
語音合成是實現人機語音交互,跟機器說話,創建一個有聽和講能力的交互系統所必需的關鍵技術。隨着語音技術的發展,百度自主研發了語音合成系統(TTS),功能是接受用戶發送的文本,生成語音發送給用戶。
對本文中將提到的概念約定以下:
語音合成:將文本合成爲語音,即聲音文件。
合成引擎:將文本合成爲語音的核心模塊。
TTS:Text To Speech,即「從文本到語音」。
BDTTSClient:語音合成 SDK 簡稱,詳見下條。
語音合成 SDK:即本開發包,文中簡稱爲 BDTTSClient。BDTTSClient 是一個封裝了網絡收發、音頻播放功能的語音合成解決方案。藉助 BDTTSClient 能夠快速地在應用程序中集成語音合成功能。 json
1.下載Android 平臺 HTML5+ SDK 。最好Android studio
2.註冊百度開發者,建立應用,開通服務,請參考集成指南。
3.下載在線語音合成SDK_Android版。 windows
1.先導入5+SDK就很少說了,參考Android平臺第三方插件開發指導。
2.添加BDTTSClient到工程(將開發包中的 libs 目錄總體拷貝到工程目錄,libs 目錄包括了各平臺的 SO 庫,開發者視應用須要能夠進行刪減。galaxy_lite.jar 是百度 Android 公共基礎庫。)
3.權限聲明(須要在 AndroidManifest.xml 文件,增長以上三個權限) api
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
集成java代碼
import org.json.JSONArray;
import com.baidu.speechsynthesizer.SpeechSynthesizer;
import com.baidu.speechsynthesizer.SpeechSynthesizerListener;
import com.baidu.speechsynthesizer.publicutility.SpeechError;
import android.media.AudioManager;
import android.util.Log;
import io.dcloud.common.DHInterface.IWebview;
import io.dcloud.common.DHInterface.StandardFeature;
import io.dcloud.common.util.JSUtil;
public class baidutts extends StandardFeature implements SpeechSynthesizerListener{
private IWebview iwv ;
private String text;
private SpeechSynthesizer speechSynthesizer;
private static final String TAG = "zlz";
public void speak(IWebview pWebview, JSONArray array)
{
iwv = pWebview;
String CallBackID = array.optString(0);
JSONArray newArray = new JSONArray();
newArray.put(array.optString(1));
//前臺傳過來的文本信息
text = array.optString(1);
//Log.i(TAG, text);
initialTts();
JSUtil.execCallback(pWebview, CallBackID, newArray, JSUtil.OK, false);
}
//百度TTS初始化
private void initialTts() {
speechSynthesizer = new SpeechSynthesizer(iwv.getContext(),
"holder", this);
// 此處須要將setApiKey方法的兩個參數替換爲你在百度開發者中心註冊應用所獲得的apiKey和secretKey
speechSynthesizer.setApiKey("your-apiKey", "your-secretKey");
speechSynthesizer.setAudioStreamType(AudioManager.STREAM_MUSIC);
//setVolumeControlStream(AudioManager.STREAM_MUSIC);
new Thread(new Runnable() {
@Override
public void run() {
setParams();
int ret = speechSynthesizer.speak(text);
if (ret != 0) {
Log.i(TAG,"開始合成器失敗" );
}
}
}).start();
}
private void setParams() {
speechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEAKER, "0");
speechSynthesizer.setParam(SpeechSynthesizer.PARAM_VOLUME, "5");
speechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEED, "5");
speechSynthesizer.setParam(SpeechSynthesizer.PARAM_PITCH, "5");
speechSynthesizer.setParam(SpeechSynthesizer.PARAM_AUDIO_ENCODE, SpeechSynthesizer.AUDIO_ENCODE_AMR);
speechSynthesizer.setParam(SpeechSynthesizer.PARAM_AUDIO_RATE, SpeechSynthesizer.AUDIO_BITRATE_AMR_15K85);
}
@Override
public void onBufferProgressChanged(SpeechSynthesizer arg0, int arg1) {}
@Override
public void onCancel(SpeechSynthesizer arg0) {}
@Override
public void onError(SpeechSynthesizer arg0, SpeechError arg1) {}
@Override
public void onNewDataArrive(SpeechSynthesizer arg0, byte[] arg1, boolean arg2) {}
@Override
public void onSpeechFinish(SpeechSynthesizer arg0) {}
@Override
public void onSpeechPause(SpeechSynthesizer arg0) {}
@Override
public void onSpeechProgressChanged(SpeechSynthesizer arg0, int arg1) {}
@Override
public void onSpeechResume(SpeechSynthesizer arg0) {}
@Override
public void onSpeechStart(SpeechSynthesizer arg0) {}
@Override
public void onStartWorking(SpeechSynthesizer arg0) {}
@Override
public void onSynthesizeFinish(SpeechSynthesizer arg0) {}
}
前臺javascript代碼
document.addEventListener( "plusready", function()
{
var _BARCODE = 'kxdPlugins',
B = window.plus.bridge;
var kxdPlugins =
{
// 聲明異步返回方法
speak : function (Argus, successCallback, errorCallback )
{
var success = typeof successCallback !== 'function' ? null : function(args)
{
successCallback(args);
},
fail = typeof errorCallback !== 'function' ? null : function(code)
{
errorCallback(code);
};
callbackID = B.callbackId(success, fail);
// 通知Native層plugintest擴展插件運行」speak」方法
return B.exec(_BARCODE, "speak", [callbackID, Argus]);
}
};
window.plus.kxdPlugins = kxdPlugins;
}, true );
使用方式
和普通的API調用方式同樣:plus.kxdPlugins.speak("這是語音播放的文字內容");
注意事項
1.在/assets/data/properties.xml中添加插件權限。
2.在/assets/apps/appid/www/manifest.json 中添加對應插件權限。
3.在/AndroidManifest.xml 文件中添加對應的百度語音合成權限。
三,
前臺javascript代碼
Argus]); } }; window.plus.kxdPlugins = kxdPlugins; }, true );
和普通的API調用方式同樣:plus.kxdPlugins.speak("這是語音播放的文字內容");
1.在/assets/data/properties.xml中添加插件權限。
2.在/assets/apps/appid/www/manifest.json 中添加對應插件權限。
3.在/AndroidManifest.xml 文件中添加對應的百度語音合成權限。
這是調用百度語音API
四,Android語音
code:
public class TextToSpeechDemo implements TextToSpeech.OnInitListener {
private final TextToSpeech mTextToSpeech;//TTS對象
private final ConcurrentLinkedQueue mBufferedMessages;//消息隊列
private Context mContext;
private boolean mIsReady;//標識符
public TextToSpeechDemo(Context context){
this.mContext=context;//獲取上下文
this.mBufferedMessages=new ConcurrentLinkedQueue();//實例化隊列
this.mTextToSpeech=new TextToSpeech(this.mContext,this);//實例化TTS
}
//初始化TTS引擎
@Override
public void onInit(int status) {
Log.i("TextToSpeechDemo",String.valueOf(status));
if(status==TextToSpeech.SUCCESS){
int result = this.mTextToSpeech.setLanguage(Locale.CHINA);//設置識別語音爲中文
synchronized (this){
this.mIsReady=true;//設置標識符爲true
for(String bufferedMessage : this.mBufferedMessages){
speakText(bufferedMessage);//讀語音
}
this.mBufferedMessages.clear();//讀完後清空隊列
}
}
}
//釋放資源
public void release(){
synchronized (this){
this.mTextToSpeech.shutdown();
this.mIsReady=false;
}
}
//更新消息隊列,或者讀語音
public void notifyNewMessage(String lanaugh){
String message=lanaugh;
synchronized (this){
if(this.mIsReady){
speakText(message);
}else{
this.mBufferedMessages.add(message);
}
}
}
//讀語音處理
private void speakText(String message){
Log.i("liyuanjinglyj",message);
HashMap params=new HashMap();
params.put(TextToSpeech.Engine.KEY_PARAM_STREAM,"STREAM_NOTIFICATION");//設置播放類型(音頻流類型)
this.mTextToSpeech.speak(message, TextToSpeech.QUEUE_ADD, params);//將這個發音任務添加當前任務以後
this.mTextToSpeech.playSilence(100,TextToSpeech.QUEUE_ADD,params);//間隔多長時間
}
}
固然通常手機是不支持中文的能夠百度下載訊飛TTS引擎後在測試。見最後附圖。
因爲TTS引擎的初始化是異步的,因此在執行實際的文字轉語音以前須要把消息放到隊列中。
能夠給TTS引擎發送多個參數。前面展現瞭如何決定口語消息使用的音頻流。在這種狀況下,通知聲音也使用相同的音頻流。
最後,若是處理連續多個消息,最好在每一個消息結束後暫停一會在播放下一個消息。這樣作會清楚的告訴用戶消息的結束和開始。
效果圖:
五,安裝語音庫,假如要中文發音,使用科大訊飛語音3.0
code:
package com.example.tts;
import java.util.Locale;
import android.speech.tts.TextToSpeech;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity
implements TextToSpeech.OnInitListener{
TextToSpeech textToSpeech = null; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textToSpeech = new TextToSpeech(this, this);
textToSpeech.speak("此處無聲", TextToSpeech.QUEUE_ADD, null); } @Override
public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu);
return true; }
protected void onDestroy() { super.onDestroy();
if (textToSpeech!=null) { textToSpeech.shutdown(); } } @Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
textToSpeech.speak("此處有聲", TextToSpeech.QUEUE_FLUSH, null);
return true; }
return super.onOptionsItemSelected(item); } @Override
public void onInit(int status) { // TODO Auto-generated method stub
if (status == TextToSpeech.SUCCESS) {
int result = textToSpeech.setLanguage(Locale.CHINESE);
if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED ||
result == TextToSpeech.ERROR) {
Toast.makeText(this, "數據丟失或語言不支持",
Toast.LENGTH_SHORT).show(); }
if (result == TextToSpeech.LANG_AVAILABLE) {
Toast.makeText(this, "支持該語言", Toast.LENGTH_SHORT).show(); }
Toast.makeText(this, "初始化成功", Toast.LENGTH_SHORT).show(); } } }
無需任何權限,這裏有個問題,就是在動態建立一個對象以後,在onCreate裏面調用speak方法,並不能發出聲音。
能夠把文字保存爲語音文件,也能夠讀取語音文件
public void saveToFile(TextToSpeech speech,String text,String file) { String destFileName = "/sdcard/tts/"+file+".wav"; speech.synthesizeToFile(text, null, destFileName); } public void readFromFile(TextToSpeech speech,String file) { String destFileName = "/sdcard/tts/"+file+".wav"; speech.addSpeech("2", destFileName); speech.speak("2", TextToSpeech.QUEUE_ADD, null); }
這樣就能夠了。
接下來說一下如何實現語音識別
語音識別首先能夠考慮使用科大訊飛,可是目前使用必需要聯網,並且申請一個APPID。
用起來不難
一、語音合成功能
private SpeechSynthesizer speechSynthesizer;
SpeechUser.getUser().login(MainActivity.this, null, null, "appid=54d304cf", null);
speechSynthesizer = SpeechSynthesizer.createSynthesizer(this);
speechSynthesizer.setParameter(SpeechConstant.VOICE_NAME, "xiaoyan");
speechSynthesizer.setParameter(SpeechConstant.SPEED, "50");
speechSynthesizer.setParameter(SpeechConstant.VOLUME, "50");
speechSynthesizer.setParameter(SpeechConstant.PITCH, "50");
String text = editText.getText().toString();speechSynthesizer.startSpeaking(text, null);
註冊--設置--播放。文字轉語音功能須要聯網,但不須要正確的APPID,能夠直接使用。可是語音識別就須要聯網和正確的APPID
二、語音識別
private RecognizerDialog recognizerDialog;
SpeechUser.getUser().login(MainActivity.this, null, null, "appid=54d304cf", null);
recognizerDialog = new RecognizerDialog(this);
recognizerDialog.setParameter(SpeechConstant.DOMAIN, "iat");
recognizerDialog.setParameter(SpeechConstant.SAMPLE_RATE, "16000");
//顯示Dialog
recognizerDialog.setListener(dialogListener);
recognizerDialog.show();
private RecognizerDialogListener dialogListener = new RecognizerDialogListener() {
//識別結果回調
@Override
public void onResult(RecognizerResult arg0, boolean arg1) {
// TODO Auto-generated method stub
String text = JsonParser.parseIatResult(arg0.getResultString());
editText.append(text);
editText.setSelection(editText.length());
}
//識別結束回調
@Override
public void onError(SpeechError arg0) {
// TODO Auto-generated method stub
}
};
package com.example.viocedemo;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;
import android.text.TextUtils; /** * 對雲端返回的Json結果進行解析 * @author iFlytek * @since 20131211 */ public class JsonParser { /** * 聽寫結果的Json格式解析 * @param json * @return */
public static String parseIatResult(String json) {
if(TextUtils.isEmpty(json))
return ""; 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++) {
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(); } }
這樣就能夠實現語音輸入了,很是簡單。
PHP文字轉語音,這類的文章少,可能要集成PHP第三方插件來實現。
Android默認沒有安裝TTS數據包,沒法文字轉語音,而在設置裏推薦的語音包是Pico TTS,並不支持中文,若是須要讀中文,須要下載另外的第三方語音包,如:eSpeak,Svox,我的建議Svox,eSpeak很是生硬,並且不少漢字都讀不出,不支持中英文混讀(英文當拼音讀)。下載連接本身Google下吧,不少軟件市場都有下載。下載安裝後打開設置-語音輸入和輸出-文字轉語音設置,勾選Svox Classic TTS,語言選擇中文或廣東話(Svox安裝後還要下載安裝相應的語言包的,相似插件)。
中文普通話語音包:http://www.nduoa.com/web/soft/show/id/4954
粵語語音包:http://www.nduoa.com/web/soft/show/id/4955
實現普通話,粵語
文字轉語音編程能夠實現更多地方語言的擴展,好比四川話,閩南語,江西話等,辦法是有的,能夠提供更多的語音擴展。。。。。。
文字轉語音,相信再也不是英文,漢語,韓語,也許是家鄉話更親切。
拭目以待
end