重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
之前研究了基于UDP的文字传输 点击打开链接 ,以及Android端的语音录制 点击打开链接 ,这篇文章就记录一下Android端局域网内的语音传输,简单的实现语音对讲,当然里面还存在着很多问题,包括语音不清晰啊、杂音多啊,不管了,先听见声音就行了。测试的时候两部手机,上图:
“只有客户发展了,才有我们的生存与发展!”这是创新互联的服务宗旨!把网站当作互联网产品,产品思维更注重全局思维、需求分析和迭代思维,在网站建设中就是为了建设一个不仅审美在线,而且实用性极高的网站。创新互联对网站设计制作、做网站、网站制作、网站开发、网页设计、网站优化、网络推广、探索永无止境。
程序写了两个线程,一个用于录制AudioRecordThread,一个用于播放AudioTrackThread.
(一)录制与发送
@Override
public void run() {
if (mSocket == null)
return;
try {
mStartTime = System.currentTimeMillis();
audioRec.startRecording();
while (flag) {
try {
byte[] bytes_pkg = buffer.clone();
if (mRecordQueue.size() = 2) {
int length = audioRec.read(buffer, 0, minBufferSize);
//获取音量大小
mVolume = getAudioColum(buffer);
System.out.println(TAG + "= " + mVolume);
Message message = mHandler.obtainMessage();
message.arg1 = (int) mVolume;
mHandler.sendMessage(message);
DatagramPacket writePacket;
InetAddress inet = InetAddress.getByName(inetAddressName);
writePacket = new DatagramPacket(buffer, length, inet, PORT);
writePacket.setLength(length);
System.out.println("AudioRTwritePacket = " + writePacket.getData().toString());
mSocket.send(writePacket);
}
mRecordQueue.add(bytes_pkg);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
audioRec.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
里面包含了获取音量大小,便于在页面上面展示,方法参考了 点击打开链接
private double getAudioColum(byte[] buffer) {
double sumVolume = 0.0;
double avgVolume = 0.0;
double volume = 0.0;
for (int i = 0; i buffer.length; i += 2) {
int v1 = buffer[i] 0xFF;
int v2 = buffer[i + 1] 0xFF;
int temp = v1 + (v2 8);// 小端
if (temp = 0x8000) {
temp = 0xffff - temp;
}
sumVolume += Math.abs(temp);
}
avgVolume = sumVolume / buffer.length / 2;
volume = Math.log10(1 + avgVolume) * 10;
return volume;
}
(二)接收与播放
@Override
public void run() {
if (mSocket == null)
return;
//从文件流读数据
audioTrk.play();
while (flag) {
DatagramPacket recevPacket;
try {
recevPacket = new DatagramPacket(buffer, 0, buffer.length);
mSocket.receive(recevPacket);
audioTrk.write(recevPacket.getData(), 0, recevPacket.getLength());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
audioTrk.stop();
}
(三)主页面 接收按钮事件
@OnClick({R.id.btn_receive})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.btn_receive:
if (btnReceive.getText().toString().equals("开始接收")) {
btnReceive.setText("停止接收");
try {
if (audioTrackThread == null) {
audioTrackThread = new AudioTrackThread();
}
new Thread(audioTrackThread).start();
} catch (SocketException e) {
e.printStackTrace();
}
} else {
btnReceive.setText("开始接收");
audioTrackThread.setFlag(false);
}
break;
}
}
(四)发送按钮事件
ivSpeak.setOnTouchListener(new View.OnTouchListener() {
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//按下按钮开始录制
ivSpeak.setText("正在说话");
//显示录音提示
relativeLayout.setVisibility(View.VISIBLE);
try {
if (audioRecordThread == null) {
audioRecordThread = new AudioRecordThread(handler);
}
audioRecordThread.setInetAddressName(tvReceiveIp.getText().toString());
audioRecordThread.setFlag(true);
new Thread(audioRecordThread).start();
} catch (SocketException e) {
e.printStackTrace();
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
//松开按钮结束录制
ivSpeak.setText("按住说话");
relativeLayout.setVisibility(View.GONE);
audioRecordThread.setFlag(false);
mStopTime = audioRecordThread.getmStopTime();
mStartTime = audioRecordThread.getmStartTime();
creatMessageBean((mStopTime - mStartTime) / 1000, true);
break;
}
return true;
}
});
如果是打算自己从零开始研发,那难不难得看自己团队的技术水平,觉得有难度的话,不如试一试和第三方开发商合作,诸如有20年经验的ZEGO即构科技团队,他们自主研发了实时语音SDK,实现语音聊天功能很简单的,直接接入SDK就可以了。
android开放实现语音通话最快的方式直接用现成SDK,推荐zego实时语音通话sdk.
以 2 人间的实时语音为例,主要流程如下:
android开放实现语音通话最快的方式直接用现成SDK,可以试试ZEGO即构科技的实时语音SDK,实现流程也比较便捷,通过四行代码,三十分钟就可以搭建聊天场景了
虽然视觉上的反馈通常是给用户提供信息最快的方式,但这要求用户把注意力设备上。当用户不能查看设备时,则需要一些其他通信的方法。Android提供了强大的文字转语音Text-to-Speech,TTS API。使开发者能够在应用中添加语音通知和其他语音反馈功能,而不要求用户看着屏幕。
下面的代码展示了如何使用TTS API:
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引擎发送多个参数。前面展示了如何决定口语消息使用的音频流。在这种情况下,通知声音也使用相同的音频流。
最后,如果处理连续多个消息,最好在每个消息结束后暂停一会在播放下一个消息。这样做会清楚的告诉用户消息的结束和开始。
android语音,有可能是一些语音识别软件,可以通过讲话来开启一些应用,还有一些类似于微信的,可以讲话、qq也是。