Android MediaCodec录屏时同时录取麦克风音频和内部音频
时间: 2023-12-14 12:38:56 浏览: 222
Android 中录制屏幕并同时录取麦克风音频和内部音频需要使用 MediaProjection 和 MediaCodec。下面是一个大致的思路:
1. 获取 MediaProjection 对象。
```
MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
Intent permissionIntent = mediaProjectionManager.createScreenCaptureIntent();
startActivityForResult(permissionIntent, REQUEST_CODE);
```
2. 在 onActivityResult() 方法中获取 MediaProjection 对象。
```
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {
mMediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);
}
}
```
3. 创建 AudioRecord 对象,用于录取麦克风音频。
```
private void startRecordingAudio() {
mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, SAMPLE_RATE_IN_HZ,
CHANNEL_CONFIG, AUDIO_FORMAT, BUFFER_SIZE_IN_BYTES);
mAudioRecord.startRecording();
}
```
4. 创建 MediaCodec 对象,用于编码屏幕和音频数据。
```
private void prepareEncoder() {
mMediaCodec = MediaCodec.createEncoderByType(MIME_TYPE);
MediaFormat mediaFormat = MediaFormat.createVideoFormat(MIME_TYPE, VIDEO_WIDTH, VIDEO_HEIGHT);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, VIDEO_BITRATE);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, VIDEO_FRAME_PER_SECOND);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, VIDEO_I_FRAME_INTERVAL);
mMediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mInputSurface = mMediaCodec.createInputSurface();
mMediaCodec.start();
}
```
5. 在录制过程中,循环从麦克风和 MediaCodec 中读取音频和视频数据,并将它们合并后写入 MP4 文件。
```
private void record() {
while (mIsRecording) {
int inputBufferIndex = mMediaCodec.dequeueInputBuffer(TIMEOUT_US);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = mMediaCodec.getInputBuffer(inputBufferIndex);
inputBuffer.clear();
int size = mVirtualDisplay.getDisplay().getWidth() * mVirtualDisplay.getDisplay().getHeight() * 4;
mVirtualDisplay.getDisplay().getRealMetrics(mDisplayMetrics);
Bitmap bitmap = mImageReader.acquireLatestImage().getPlanes()[0].getBuffer().toBitmap();
bitmap = Bitmap.createScaledBitmap(bitmap, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels, false);
inputBuffer.put(bitmapToNV21(bitmap, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels));
mMediaCodec.queueInputBuffer(inputBufferIndex, 0, size, System.nanoTime() / 1000, 0);
}
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = mMediaCodec.dequeueOutputBuffer(bufferInfo, TIMEOUT_US);
if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
MediaFormat mediaFormat = mMediaCodec.getOutputFormat();
mMediaMuxerWrapper.addTrack(mediaFormat);
mMediaMuxerWrapper.start();
} else if (outputBufferIndex >= 0) {
ByteBuffer outputBuffer = mMediaCodec.getOutputBuffer(outputBufferIndex);
if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
bufferInfo.size = 0;
}
if (bufferInfo.size != 0) {
bufferInfo.presentationTimeUs = System.nanoTime() / 1000;
mMediaMuxerWrapper.writeSampleData(outputBuffer, bufferInfo);
}
mMediaCodec.releaseOutputBuffer(outputBufferIndex, false);
}
int readResult = mAudioRecord.read(mAudioBuffer, 0, mAudioBuffer.length);
if (readResult > 0 && mIsRecording) {
mMediaMuxerWrapper.writeAudioData(mAudioBuffer, readResult);
}
}
}
```
其中 `mMediaMuxerWrapper` 是一个封装了 MediaMuxer 的工具类,用于将音频和视频数据写入 MP4 文件。
需要注意的是,上面的代码仅供参考,实际应用中可能存在一些问题,例如音频和视频的同步问题等,在实际使用中需要根据具体情况进行调整。
阅读全文