关于android:如何在视频系统中捕获和编码音频_Android
How to capture and encode audio in a video system_Android
我正在尝试在 android 中构建一个开源视频系统,因为我们无法访问封闭系统中的数据。在这个系统中,我们可以修改摄像头捕获的原始数据。
我使用 MediaCodec 和 MediaMux 来完成视频数据编码和复用工作,而且效果很好。但我不知道音频部分。我使用 onFramePreview 来获取每一帧并逐帧进行编码/混合工作。但是我如何同时进行音频录制(我的意思是逐帧捕获音频,对其进行编码并将数据发送到 MediaMux)。
我做了一些研究。似乎我们使用audiorecorder来获取音频的原始数据。但是audiorecorder做一个持续的录音工作,我不认为它可以工作。
谁能给我一个提示?谢谢!
像这样创建audioRecorder:
private AudioRecord getRecorderInstance() {
AudioRecord ar = null; try { //Get a audiorecord int N = AudioRecord.getMinBufferSize(8000,AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_PCM_16BIT); ar = new AudioRecord(AudioSource.MIC, 8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, N*10); } catch (Exception e) { } |
为编码和复用准备和发送数据,像这样是单独的线程:
public class MicrophoneInput implements Runnable {
@Override public void run() { // Buffer for 200 milliseconds of data, e.g. 400 samples at 8kHz. byte[] buffer200ms = new byte[8000 / 10]; try { //process buffer i.e send to encoder |
相关讨论
- 谢谢你,@马龙。我已经尝试过了,但我遇到了一些麻烦。我应该把函数 audioRecord.startRecording 放在哪里?我使用回调函数 onPreviewFrame 来获取每一帧的数据并对这些数据进行编码/复用。我尝试将 startRecording 放在 onPreviewFrame 和 onPreviewFrame 之前,但两者都可以。此外,我使用 AsyncTask 进行编码背景(onPreivewFrame 逐帧调用该任务)。如果我为 audioRecord 打开另一个线程,如何为复用器提供逐帧音频?谢谢!
-
我在 camera.startPreview() 之后有 audioRecord.startRecording。主要思想是视频被编码并发送到相机线程中的复用器。音频链存在于自己的线程中\\
unnable 在 while{} 中循环,并在样本准备好(此处为 200 毫秒)时从 audioRecorder 读取音频样本,然后发送到编码器和复用器。 Runnable 与 audioRecord start 一起创建\\\\started: MicrophoneInput mi = new MicrophoneInput(); audioThread = 新线程(mi); - 再想一想:可以在 onPreviewFrame 中添加一个同步对象,以便在每个进入的视频帧上推送音频线程。因此每个视频帧都会触发音频缓冲区在单独的线程中发送到编码器。但它需要为 audioRecorder 分配更精确的缓冲区
- 谢谢你。并感谢您解决了我的两个问题。我对如何将缓冲区从该线程发送到 onPreiewFrame 感到困惑。我们如何使它异步?我们只是让它每 200 毫秒发送一次(按时间控制)还是其他什么?你能提供更多细节吗?谢谢!
- 您需要创建 2 个 mediacodec 实例,一个用于音频,另一个用于视频,正确配置它们。在它将数据从 onPrevieFrame 发送到 videoencoder 之后,从 MicrophoneInput 中的 run() 发送到 audioencoder。只需使用循环从 audioRecorder 获取数据并发送到编码器。性能改进的空间肯定存在。并且始终将正确的时间戳发送到编码器输入 - 多路复用器基于它进行同步
- 根据我的理解,audioRecorder 的工作方式如下:当您要求 audioRecorder.read(buffer200ms, 0, buffer200ms.length); 时,它会填充内部线程中的内部缓冲区。它只是尝试将 200ms 从内部缓冲区复制到 buffer200ms。如果内部缓冲区中的时间少于 200 毫秒,它将返回实际复制的数据大小。分配 1 秒的缓冲区并以不那么频繁的方式进行读取可能会更好
- 谢谢你详细说明。所以我们在run()中编写音频录制和编码函数,在onPreviewFrame中编写视频录制和编码函数。我们确保编码器的时间戳是正确的,然后我们将数据发送到 Muxer。谢谢!