Android MediaCodec 录制音频功能完整代码
时间: 2023-12-23 09:06:20 浏览: 124
Android 实时MediaCodec音频硬编解码播放
3星 · 编辑精心推荐
以下是一个简单的 Android MediaCodec 录制音频的完整代码示例:
```java
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.media.MediaMuxer;
import android.os.Build;
import android.os.Environment;
import android.util.Log;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
public class AudioRecorder {
private static final String TAG = "AudioRecorder";
private static final String AUDIO_MIME_TYPE = "audio/mp4a-latm";
private static final int AUDIO_SAMPLE_RATE = 44100; // 44.1kHz
private static final int AUDIO_CHANNEL_COUNT = 1; // mono
private static final int AUDIO_BIT_RATE = 64000;
private static final int BUFFER_SIZE = 2 * AudioRecord.getMinBufferSize(AUDIO_SAMPLE_RATE,
AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
private MediaCodec mEncoder;
private MediaMuxer mMuxer;
private int mTrackIndex = -1;
private boolean mMuxerStarted = false;
private long mStartTime = 0;
public void startRecording() throws IOException {
File outputFile = new File(Environment.getExternalStorageDirectory(),
"audio_record.mp4");
mEncoder = MediaCodec.createEncoderByType(AUDIO_MIME_TYPE);
MediaFormat format = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, AUDIO_MIME_TYPE);
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, AUDIO_SAMPLE_RATE);
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, AUDIO_CHANNEL_COUNT);
format.setInteger(MediaFormat.KEY_BIT_RATE, AUDIO_BIT_RATE);
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, BUFFER_SIZE);
}
mEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mEncoder.start();
mMuxer = new MediaMuxer(outputFile.getAbsolutePath(), MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
ByteBuffer[] encoderOutputBuffers = mEncoder.getOutputBuffers();
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
mTrackIndex = -1;
mMuxerStarted = false;
int sampleRate = AUDIO_SAMPLE_RATE;
int channelCount = AUDIO_CHANNEL_COUNT;
long presentationTimeUs = 0;
while (true) {
int inputBufferIndex = mEncoder.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = mEncoder.getInputBuffer(inputBufferIndex);
inputBuffer.clear();
int bytesRead = // read audio data into the inputBuffer
if (bytesRead == -1) { // eof
mEncoder.queueInputBuffer(inputBufferIndex, 0, 0, presentationTimeUs,
MediaCodec.BUFFER_FLAG_END_OF_STREAM);
break;
} else {
int inputBufferCapacity = inputBuffer.capacity();
int size = inputBufferCapacity < bytesRead ? inputBufferCapacity : bytesRead;
inputBuffer.put(audioData, 0, size);
presentationTimeUs = (long) (1_000_000L * bytesRead / (2 * channelCount * sampleRate));
mEncoder.queueInputBuffer(inputBufferIndex, 0, size, presentationTimeUs, 0);
}
}
int outputBufferIndex = mEncoder.dequeueOutputBuffer(bufferInfo, 0);
if (outputBufferIndex >= 0) {
ByteBuffer outputBuffer = encoderOutputBuffers[outputBufferIndex];
if (!mMuxerStarted) {
MediaFormat newFormat = mEncoder.getOutputFormat();
mTrackIndex = mMuxer.addTrack(newFormat);
mMuxer.start();
mStartTime = System.nanoTime();
mMuxerStarted = true;
}
if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
bufferInfo.size = 0;
}
if (bufferInfo.size != 0) {
outputBuffer.position(bufferInfo.offset);
outputBuffer.limit(bufferInfo.offset + bufferInfo.size);
mMuxer.writeSampleData(mTrackIndex, outputBuffer, bufferInfo);
}
mEncoder.releaseOutputBuffer(outputBufferIndex, false);
} else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
MediaFormat newFormat = mEncoder.getOutputFormat();
mTrackIndex = mMuxer.addTrack(newFormat);
mMuxer.start();
mStartTime = System.nanoTime();
mMuxerStarted = true;
}
}
release();
}
private void release() {
if (mEncoder != null) {
mEncoder.stop();
mEncoder.release();
mEncoder = null;
}
if (mMuxer != null) {
if (mMuxerStarted) {
mMuxer.stop();
}
mMuxer.release();
mMuxer = null;
}
}
}
```
注意,这只是一个简单的示例,实际应用中还需要考虑错误处理、音频数据来源和如何停止录制等问题。
阅读全文