一,jsp 网页使用JavaScript来实现文字转语音即TTS,TEXT TO speach,
比如:
javascript语音播报 可用于排队叫号 功能实现
还是微软官方的方便简单,不然文字转语音在网页上播报这种功能真就麻烦了,特别是汉字转语音播报。这是使用js来实现的。
其次,通过Java实现中文到英文朗读出来
code:
import .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 x.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 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); (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"); (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"); (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.ActionListener(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); (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().(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();
} }); }}
图:
二,通过
Android插件,TTS语音合成(文字转化语音)
语音合成是实现人机语音交互,跟机器说话,建立一个有听和讲能力的交互系统所必需的关键技术。随着语音技术的发展,百度自主研发了语音合成系统(TTS),功能是接受用户发送的文本,生成语音发送给用户。
对本文中将提到的概念约定如下:语音合成:将文本合成为语音,即声音文件。合成引擎:将文本合成为语音的核心模块。TTS:Text To Speech,即“从文本到语音”。BDTTSClient:语音合成 SDK 简称,详见下条。语音合成 SDK:即本开发包,文中简称为 BDTTSClient。BDTTSClient 是一个封装了网络收发、音频播放功能的语音合成解决方案。借助 BDTTSClient 可以快速地在应用程序中集成语音合成功能。
准备事项
1.下载Android 平台 HTML5+ SDK 。最好Android studio
2.注册百度开发者,创建应用,开通服务,请参考。 3.下载在线语音合成SDK_Android版。实现步骤
1.先导入5+SDK就不多说了,参考。
2.添加BDTTSClient到工程(将开发包中的 libs 目录整体拷贝到工程目录,libs 目录包括了各平台的 SO 库,开发者视应用需要可以进行删减。galaxy_lite.jar 是百度 Android 公共基础库。) 3.权限声明(需要在 AndroidManifest.xml 文件,增加以上三个权限)集成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。
用起来不难
1、语音合成功能
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
2、语音识别
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安装后还要下载安装相应的语言包的,类似插件)。
中文普通话语音包:
粤语语音包:实现普通话,粤语
文字转语音编程可以实现更多地方语言的扩展,比如四川话,闽南语,江西话等,办法是有的,可以提供更多的语音扩展。。。。。。
文字转语音,相信不再是英文,汉语,韩语,也许是家乡话更亲切。
拭目以待
end