Android MediaCodec录屏时同时录制系统音频功能实现代码
时间: 2023-12-14 13:39:11 浏览: 103
在 Android 上录制屏幕并同时录制系统音频可以通过使用 MediaCodec 和 MediaProjection 来实现。下面是一个简单的示例代码:
```java
public class ScreenRecorder {
private static final String TAG = "ScreenRecorder";
private static final String MIME_TYPE = "video/avc";
private static final int FRAME_RATE = 30;
private static final int I_FRAME_INTERVAL = 10;
private static final int BIT_RATE = 6000000;
private static final int TIMEOUT_US = 10000;
private MediaProjection mMediaProjection;
private MediaCodec mMediaCodec;
private VirtualDisplay mVirtualDisplay;
private Surface mInputSurface;
private boolean mIsRecording;
private AudioRecord mAudioRecord;
private Thread mAudioThread;
private boolean mIsAudioRecording;
public void startRecording(Context context, MediaProjection mediaProjection) throws IOException {
mMediaProjection = mediaProjection;
// 初始化 MediaCodec
MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, displayWidth, displayHeight);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, I_FRAME_INTERVAL);
mMediaCodec = MediaCodec.createEncoderByType(MIME_TYPE);
mMediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mInputSurface = mMediaCodec.createInputSurface();
mMediaCodec.start();
// 创建 VirtualDisplay
mVirtualDisplay = mMediaProjection.createVirtualDisplay(TAG,
displayWidth, displayHeight, displayDensity,
DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC,
mInputSurface, null, null);
// 启动音频录制
startAudioRecording();
mIsRecording = true;
}
public void stopRecording() {
mIsRecording = false;
// 停止音频录制
stopAudioRecording();
if (mMediaProjection != null) {
mMediaProjection.stop();
mMediaProjection = null;
}
if (mVirtualDisplay != null) {
mVirtualDisplay.release();
mVirtualDisplay = null;
}
if (mMediaCodec != null) {
mMediaCodec.stop();
mMediaCodec.release();
mMediaCodec = null;
}
if (mInputSurface != null) {
mInputSurface.release();
mInputSurface = null;
}
}
private void startAudioRecording() {
int sampleRate = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_SYSTEM);
int minBufferSize = AudioRecord.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT);
mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.REMOTE_SUBMIX, sampleRate,
AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize);
mIsAudioRecording = true;
mAudioThread = new Thread(new Runnable() {
@Override
public void run() {
byte[] buffer = new byte[minBufferSize];
while (mIsAudioRecording) {
int readSize = mAudioRecord.read(buffer, 0, minBufferSize);
if (readSize > 0) {
ByteBuffer[] inputBuffers = mMediaCodec.getInputBuffers();
int inputBufferIndex = mMediaCodec.dequeueInputBuffer(TIMEOUT_US);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(buffer);
long pts = System.nanoTime() / 1000;
mMediaCodec.queueInputBuffer(inputBufferIndex, 0, readSize, pts, 0);
}
}
}
mAudioRecord.stop();
mAudioRecord.release();
mAudioRecord = null;
}
});
mAudioThread.start();
mAudioRecord.startRecording();
}
private void stopAudioRecording() {
mIsAudioRecording = false;
try {
mAudioThread.join();
} catch (InterruptedException e) {
Log.e(TAG, "stopAudioRecording: ", e);
}
}
}
```
需要注意的是,上述代码中的 `AudioRecord` 使用了 `MediaRecorder.AudioSource.REMOTE_SUBMIX`,这是一种特殊的音频源,可以录制系统音频。但是并不是所有的设备都支持 `REMOTE_SUBMIX`,如果你的设备不支持,那么你就无法录制系统音频了。
阅读全文