如何构建低延迟音频流 Android 应用程序

问题描述 投票:0回答:2

我们正在尝试将实时音频记录从手机麦克风流式传输到服务器,但遇到了 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();
    }
}
java android android-studio audio streaming
2个回答
0
投票

迟到的答案,但是,就其价值而言,Android 上的主要瓶颈通常是音频捕获最小缓冲区大小,没有多少设备能够提供小缓冲区。您得到什么值?

关于 API,如果您还没有查看过,您可能需要查看此文档:

https://developer.android.com/ndk/guides/audio/audio-latency

然后,您可以在接收器端进行缓冲,以补偿无法满足所需音频比特率的瞬时高网络负载:这是流的延迟和稳定性之间的权衡,缓冲区欠载将转化为可听的音损。您需要选择一个传输协议、编解码器和媒体播放器,以最大限度地减少缓冲。


0
投票

有一个用于在 Android 上启用低延迟的新清单: https://developer.android.com/games/sdk/oboe/low-latency-audio#oboe

它专注于游戏,但大多数适用于任何应用程序。

  1. 使用双簧管
  2. 请求性能模式“低延迟”
  3. 请求共享模式“独占”
  4. 使用 48000 Hz 或 Oboe 采样率转换器
  5. 将使用情况设置为 AAUDIO_USAGE_GAME
  6. 使用数据回调
  7. 避免回调中阻塞操作
  8. 将缓冲区大小调整为“双缓冲区”
© www.soinside.com 2019 - 2024. All rights reserved.