我们正在尝试将实时音频记录从手机麦克风流式传输到服务器,但遇到了 200 毫秒的延迟,并希望将其最小化。
是否有一个好的 API/有效的方法或协议来做到这一点? 我们考虑以某种方式使用 SIP/RTP 协议,它会更有效吗?
这是代码,您建议更改什么?
package com.awesome.audiostream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
private Button startButton,stopButton;
public byte[] buffer;
public static DatagramSocket socket;
private int port=12345;
AudioRecord recorder;
private int sampleRate = 176400;
private int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
int minBufSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
private boolean status = true;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
View mv = getLayoutInflater().inflate(R.layout.activity_main, null);
setContentView(mv);
startButton = (Button) findViewById (R.id.start_button);
stopButton = (Button) findViewById (R.id.stop_button);
startButton.setOnClickListener (startListener);
stopButton.setOnClickListener (stopListener);
}
private final OnClickListener stopListener = new OnClickListener() {
@Override
public void onClick(View arg0) {
status = false;
recorder.release();
Log.d("VS","Recorder released");
}
};
private final OnClickListener startListener = new OnClickListener() {
@Override
public void onClick(View arg0) {
status = true;
startStreaming();
}
};
public void startStreaming() {
Thread streamThread = new Thread(new Runnable() {
@Override
public void run() {
try {
DatagramSocket socket = new DatagramSocket();
Log.d("VS", "Socket Created");
byte[] buffer = new byte[minBufSize];
Log.d("VS","Buffer created of size " + minBufSize);
DatagramPacket packet;
// The IP address of the server receiving the audio stream
final InetAddress destination = InetAddress.getByName("192.168.43.204");
Log.d("VS", "Address retrieved");
recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,sampleRate,channelConfig,audioFormat,minBufSize*10);
Log.d("VS", "Recorder initialized");
recorder.startRecording();
while(status) {
//reading data from MIC into buffer
minBufSize = recorder.read(buffer, 0, buffer.length);
//putting buffer in the packet
packet = new DatagramPacket (buffer,buffer.length,destination,port);
socket.send(packet);
System.out.println("MinBufferSize: " +minBufSize);
}
} catch(UnknownHostException e) {
Log.e("VS", "UnknownHostException");
} catch (IOException e) {
e.printStackTrace();
Log.e("VS", "IOException");
}
}
});
streamThread.start();
}
}
迟到的答案,但是,就其价值而言,Android 上的主要瓶颈通常是音频捕获最小缓冲区大小,没有多少设备能够提供小缓冲区。您得到什么值?
关于 API,如果您还没有查看过,您可能需要查看此文档:
https://developer.android.com/ndk/guides/audio/audio-latency
然后,您可以在接收器端进行缓冲,以补偿无法满足所需音频比特率的瞬时高网络负载:这是流的延迟和稳定性之间的权衡,缓冲区欠载将转化为可听的音损。您需要选择一个传输协议、编解码器和媒体播放器,以最大限度地减少缓冲。
有一个用于在 Android 上启用低延迟的新清单: https://developer.android.com/games/sdk/oboe/low-latency-audio#oboe
它专注于游戏,但大多数适用于任何应用程序。