我正在使用 AudioRecord 在 Android 设备上的相机捕获过程中录制音频流。 由于我要处理帧数据和处理音频/视频样本,所以我不使用 MediaRecorder。
我在另一个线程中运行 AudioRecord 并调用 read() 来收集原始音频数据。 获得数据流后,我将它们送入配置为 AAC 音频编码器的 MediaCodec。
以下是我的一些关于录音机/编码器的代码:
m_encode_audio_mime = "audio/mp4a-latm";
m_audio_sample_rate = 44100;
m_audio_channels = AudioFormat.CHANNEL_IN_MONO;
m_audio_channel_count = (m_audio_channels == AudioFormat.CHANNEL_IN_MONO ? 1 : 2);
int audio_bit_rate = 64000;
int audio_data_format = AudioFormat.ENCODING_PCM_16BIT;
m_audio_buffer_size = AudioRecord.getMinBufferSize(m_audio_sample_rate, m_audio_channels, audio_data_format) * 2;
m_audio_recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, m_audio_sample_rate,
m_audio_channels, audio_data_format, m_audio_buffer_size);
m_audio_encoder = MediaCodec.createEncoderByType(m_encode_audio_mime);
MediaFormat audio_format = new MediaFormat();
audio_format.setString(MediaFormat.KEY_MIME, m_encode_audio_mime);
audio_format.setInteger(MediaFormat.KEY_BIT_RATE, audio_bit_rate);
audio_format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, m_audio_channel_count);
audio_format.setInteger(MediaFormat.KEY_SAMPLE_RATE, m_audio_sample_rate);
audio_format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
audio_format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, m_audio_buffer_size);
m_audio_encoder.configure(audio_format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
我发现AudioRecord.read()的第一次返回时间较长,而后续的read()时间间隔更接近音频数据的实时时间。 比如我的音频格式是44100Hz 16Bit 1Channel,AudioRecord的buffer size是16384,那么满buffer就是185.76ms。当我记录每次调用 read() 的系统时间并从基准时间中减去它们时,我得到以下序列:
每次读取之前的时间():0ms、345ms、543ms、692ms、891ms、1093ms、1244ms,...
我将这些原始数据以上述时间值作为 PTS 提供给音频编码器,编码器输出具有以下 PTS 的编码音频样本:
编码器输出PTS: 0ms, 185ms, 371ms, 557ms, 743ms, 928ms, ...
看起来编码器将数据的每个部分视为具有相同的时间段。我相信编码器工作正常,因为我每次都给它提供相同大小 (16384) 的原始数据。但是,如果我使用编码器输出 PTS 作为多路复用器的输入,我将获得音频内容比视频内容更快的视频。
我想问的是:
- 是否预期 AudioRecord.read() 的第一次阻塞时间更长?我确定函数调用需要超过 300 毫秒,而它只将 16384 个字节记录为 186 毫秒。这是否也是一个取决于设备/Android 版本的问题?
- 我应该怎么做才能实现音频/视频同步?我有一个解决方法来测量第一次调用 read() 的延迟时间,然后通过延迟移动音频样本的 PTS。还有其他更好的方法来处理这个问题吗?
最佳答案
将单声道输入转换为立体声。在我意识到 MediaCoder 公开的 AAC 编码器只适用于立体声输入之前,我一直在苦苦思索。
关于android - 如何使用 Android AudioRecord 和 MediaCodec 作为音频编码器正确处理 PTS?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22604756/