Android端通过Socket.io播放流式音频时声音卡顿破碎的问题求助
Android端通过Socket.io播放流式音频时声音卡顿破碎的问题求助
大家好,我最近做了一个简单的语音通话应用,逻辑是把Android设备麦克风采集的音频通过Socket.io发送到Python写的服务器,再由服务器广播给接收端,接收端拿到音频数据后播放。
现在遇到的棘手问题是:Python客户端接收并播放音频完全正常,但Android端播放时声音严重卡顿、破碎,完全没法正常使用。我已经尝试了好几种调整方案,但还是没解决问题,实在找不到问题出在哪了,想请各位帮忙看看!
我的Python服务器代码:
import eventlet from eventlet.wsgi import server as wsgi_server from socketio import Server as SocketServer, WSGIApp sio = SocketServer() socket_app = WSGIApp(sio) @sio.event def broadcast_audio(sid, data): sio.emit('audio_stream', data) wsgi_server(eventlet.listen(('', 5000)), socket_app)
Android端Java代码:
package dev.codewithcoffee.penpal; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import android.content.pm.PackageManager; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioRecord; import android.media.AudioTrack; import android.media.MediaRecorder; import android.os.AsyncTask; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import java.net.URISyntaxException; import io.socket.client.IO; import io.socket.client.Socket; import io.socket.emitter.Emitter; public class MainActivity extends AppCompatActivity { private Socket mSocket; private AudioTrack audioTrack; private int audioTrackOffset = 0; private int recordSampleRate, bufferSize; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LayoutInflater inflater = LayoutInflater.from(this); View callView = inflater.inflate(R.layout.activity_call, null); // recordSampleRate = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC); // bufferSize = AudioTrack.getMinBufferSize(recordSampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); recordSampleRate = 44100; bufferSize = 4096; audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, recordSampleRate, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM); audioTrack.play(); initializeSocket(); startBroadcastAudio(); setContentView(callView); } private void initializeSocket() { IO.Options options = new IO.Options(); options.forceNew = true; options.reconnection = true; options.reconnectionDelay = 2000; options.reconnectionDelayMax = 5000; try { mSocket = IO.socket("http://192.168.1.3:5000"); mSocket.on("audio_stream", onAudioStream); if (!mSocket.connected()) { mSocket.connect(); } } catch (URISyntaxException e) { throw new RuntimeException(e); } } private final Emitter.Listener onAudioStream = new Emitter.Listener() { @Override public void call(Object... args) { try { byte[] audioBytes = (byte[]) args[0]; audioTrack.write(audioBytes, 0, audioBytes.length); } catch (Exception e) { e.printStackTrace(); } } }; private void broadcastAudio() { if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { return; } AudioRecord audioRecorder = new AudioRecord( MediaRecorder.AudioSource.MIC, recordSampleRate, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT, bufferSize ); // Continuously read audio data from the recorder and send it to the server byte[] buffer = new byte[bufferSize]; audioRecorder.startRecording(); while (true) { int numBytesRead = audioRecorder.read(buffer, 0, bufferSize); if (numBytesRead > 0) { // Send audio data to server through socket connection mSocket.emit("broadcast_audio", buffer); } } } private class MyAsyncTask extends AsyncTask<Void, Void, Void> { @Override protected Void doInBackground(Void... params) { // Run your function here broadcastAudio(); return null; } @Override protected void onPostExecute(Void result) { // This method is called on the main thread // You can update the UI here if needed } } // Call this method to start the async task private void startBroadcastAudio() { MyAsyncTask task = new MyAsyncTask(); task.execute(); } }
我已经尝试过的调试方案:
- 手动设置不同的缓冲区大小(比如改成4096、8192等)
- 用
AudioTrack.getMinBufferSize()方法自动计算适配的缓冲区大小 - 调整采样率为Android系统原生的输出采样率
但这些尝试都没解决Android端播放卡顿破碎的问题,希望各位能帮我排查一下问题所在,谢谢!
备注:内容来源于stack exchange,提问作者Aryan Arabshahi
相关产品推荐
相关产品推荐

