需求:实现多人即时语音聊天室
实现方式:android端实现AudioRecord实时记录原生pcm流的原始录音数据,并通过websocket实时传输到后端,再由后端实时将pcm流数据分发给每个用户,用户接收到pcm流数据后通过AudioTrack进行实时播放。
注意事项:audioRecord的各种基础配置需要和audioTrack的基础配置项相对应。
扩展:需要做声音降噪,或者变声处理的,可在拿到pcm录音原始数据后进行相关的处理
1.录音端代码
private Boolean doStart() {
try {
startRecordTime = System.currentTimeMillis();
//创建MediaRecorder
//计算AudioRecord内部buffer最小缓冲区大小
bufferSize = AudioRecord.getMinBufferSize(44100,
AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
44100, AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT, Math.max(bufferSize,BUFFER_SIZE));
//记录开始录音时间 用于统计时长 时间太短就是无效录音
stopRecordTime = System.currentTimeMillis();
//开始录音
audioRecord.startRecording();
//获取录音的二进制数据 并使用websocket进行数据传输;
while(isStartRecord){
if (null != audioRecord) {
int read = audioRecord.read(mBuffer,0,BUFFER_SIZE);
if (read == AudioRecord.ERROR_INVALID_OPERATION || read == AudioRecord.ERROR_BAD_VALUE) {
Log.d("NLPService", "Could not read audio data.");
break;
}
if (read != 0 && read != -1) {
//在此可以对录制音频的数据进行二次处理 比如变声,压缩,降噪,增益等操作
//我们这里直接将pcm音频原数据写入文件 这里可以直接发送至服务器 对方采用AudioTrack进行播放原数据
// dos.write(mBuffer, 0, read);
// dos.flush();
broadcastRoomService.send(ByteString.of(mBuffer));
} else {
break;
}
}
}
}catch (RuntimeException e){
e.printStackTrace();
//捕获异常避免闪退 返回false提醒用户失败
return false;
}
return true;
}
2.webSocketService端
public class WebSocketService extends Service {
private static final String TAG = "websocket";
private WebSocket webSocket;
private WebSocketCallback webSocketCallback;
private int reconnectTimeout = 2000;
private boolean connected = false;
private int limitConnect = 20;
private int timeConnect = 0;
private Handler handler = new Handler();
public class LocalBinder extends Binder {
public WebSocketService getService() {
return WebSocketService.this;
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new LocalBinder();
}
@Override
public void onCreate() {
super.onCreate();
webSocket = connect();
initConnectCount();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
// if (webSocket != null) {
// close();
// }
reconnect();
}
private WebSocket connect() {
SharedPreferences userInfo = getSharedPreferences("userInfo", MODE_PRIVATE);
String currentUserId &#