通过WiFi在Android手机之间流式传输语音

寸阳分阴须爱惜,休负春色与时光。这篇文章主要讲述通过WiFi在Android手机之间流式传输语音相关的知识,希望能为你提供帮助。
我正试图通过WiFi将音频从1个android流式传输到另一个Android。在查看一些示例后,我制作了2个应用程序,每个应用程序中只有一个活动,1个用于捕获和发送音频,另一个用于接收。
我使用了Audiorecord和Audiotrack课程来捕捉和播放。然而,我只是听到一些噼里啪啦的声音(虽然我回复后我做了一些改变后现在停止了)
发送语音的活动。

public class VoiceSenderActivity extends Activity {private EditText target; private TextView streamingLabel; private Button startButton,stopButton; public byte[] buffer; public static DatagramSocket socket; private int port=50005; //which port?? AudioRecord recorder; //Audio Configuration. private int sampleRate = 8000; //How much will be ideal? private int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO; private int audioFormat = AudioFormat.ENCODING_PCM_16BIT; private boolean status = true; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); target = (EditText) findViewById (R.id.target_IP); streamingLabel = (TextView) findViewById(R.id.streaming_label); startButton = (Button) findViewById (R.id.start_button); stopButton = (Button) findViewById (R.id.stop_button); streamingLabel.setText("Press Start! to begin"); 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 {int minBufSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat); DatagramSocket socket = new DatagramSocket(); Log.d("VS", "Socket Created"); byte[] buffer = new byte[minBufSize]; Log.d("VS","Buffer created of size " + minBufSize); DatagramPacket packet; final InetAddress destination = InetAddress.getByName(target.getText().toString()); Log.d("VS", "Address retrieved"); recorder = new AudioRecord(MediaRecorder.Audiosource.MIC,sampleRate,channelConfig,audioFormat,minBufSize); Log.d("VS", "Recorder initialized"); recorder.startRecording(); while(status == true) {//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); }} catch(UnknownHostException e) { Log.e("VS", "UnknownHostException"); } catch (IOException e) { Log.e("VS", "IOException"); } }}); streamThread.start(); } }

接收语音的活动
public class VoiceReceiverActivity extends Activity {private Button receiveButton,stopButton; public static DatagramSocket socket; private AudioTrack speaker; //Audio Configuration. private int sampleRate = 8000; //How much will be ideal? private int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO; private int audioFormat = AudioFormat.ENCODING_PCM_16BIT; private boolean status = true; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); receiveButton = (Button) findViewById (R.id.receive_button); stopButton = (Button) findViewById (R.id.stop_button); findViewById(R.id.receive_label); receiveButton.setOnClickListener(receiveListener); stopButton.setOnClickListener(stopListener); }private final OnClickListener stopListener = new OnClickListener() {@Override public void onClick(View v) { status = false; speaker.release(); Log.d("VR","Speaker released"); }}; private final OnClickListener receiveListener = new OnClickListener() {@Override public void onClick(View arg0) { status = true; startReceiving(); }}; public void startReceiving() {Thread receiveThread = new Thread (new Runnable() {@Override public void run() {try {DatagramSocket socket = new DatagramSocket(50005); Log.d("VR", "Socket Created"); byte[] buffer = new byte[256]; //minimum buffer size. need to be careful. might cause problems. try setting manually if any problems faced int minBufSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat); speaker = new AudioTrack(AudioManager.STREAM_MUSIC,sampleRate,channelConfig,audioFormat,minBufSize,AudioTrack.MODE_STREAM); speaker.play(); while(status == true) { try {DatagramPacket packet = new DatagramPacket(buffer,buffer.length); socket.receive(packet); Log.d("VR", "Packet Received"); //reading content from packet buffer=packet.getData(); Log.d("VR", "Packet data read into buffer"); //sending data to the Audiotrack obj i.e. speaker speaker.write(buffer, 0, minBufSize); Log.d("VR", "Writing buffer content to speaker"); } catch(IOException e) { Log.e("VR","IOException"); } }} catch (SocketException e) { Log.e("VR", "SocketException"); }}}); receiveThread.start(); }}

我使用wireshark检查数据包是否正在发送,我可以看到数据包。然而,源是发送设备和目的地的MAC地址,也就像物理地址。不确定这是否相关。
那有什么问题呢?
答案嘿,有一个名为“Libstreaming”的开源库,用于通过网络使用WIFI传输语音/视频。看看吧:
https://github.com/fyhertz/libstreaming
还提供了一些示例,请仔细看看:
https://github.com/fyhertz/libstreaming-examples
我已经使用该库通过网络流式传输RTSP音频,希望它可能有用。
另一答案我试着将问题分成三部分。
第1部分
通过注释与音频相关的所有内容,确保套接字连接正常工作
第2部分
只发送来自发件人的任意文本消息[Hello WiFi],然后在接收方应用程序中接收和打印它。
第3部分
录像机是否实际工作?尝试在单独的项目中测试您的录制方式,看它是否正常工作。
使用this代码捕获麦克风并播放它。
我的经验
我曾经在一个类似的项目上工作并测试它,我做的是在录制之后我将录制的音频数据作为文件写在SD卡上
(这将是原始音频,因此大多数音乐播放器将无法播放它... mPlayer应该播放它我想)
另一答案您需要仔细考虑使用UDP(DatagramSocket类)作为您的网络协议。
UDP是一种轻量级协议,不保证维护接收数据包的顺序。这可能是音频乱码的部分原因。无序接收的数据包将导致无序播放音频数据包。在这些无序数据包的边界处,您将听到音频样本实际损坏的点击/弹出。除此之外,不保证UDP数据包成功传送。任何丢弃的数据包显然会增加任何听到的乱码或失真。
TCP(套接字类)将是获得最佳音频质量的更好选择。 TCP是一种更强大的协议,可以保持接收数据包的顺序。它还具有内置错误检查功能,并将重新发送任何丢弃的数据包。但是,由于这种注意功能,TCP具有更高的网络开销。
我开始回答说你需要仔细考虑你使用的协议。这是因为有一种情况可以根据对你重要的事情来使用。
如果你想要超低延迟播放,但很高兴牺牲音频质量,那么UDP就能工作。但是,需要进行一些实验才能找到最佳的缓冲液和样品量。
如果你想要最好的音频重新制作,零失真,但很乐意引入稍多的延迟,那么TCP就是可行的路线。
【通过WiFi在Android手机之间流式传输语音】我不能说TCP会增加多少延迟。但它有可能在不影响用户体验的情况下实施。找出答案的唯一方法是尝试并看到。

    推荐阅读