android - 视频录制和onPreviewFrame同时回调
问题描述
我正在尝试使用回调方法录制视频MediaRecorder
并获取原始帧(字节数组)onPreviewFrame
似乎没那么容易,mb这甚至不可能,我不知道......
但是我找到了一些答案(对于类似的问题),人们说您应该Camera.reconnect()
在调用MediaRecorder.start()
并再次设置预览回调后重新连接相机实例()
我尝试过这样的事情,但它不起作用(录音有效,但从onPreviewFrame
未被调用)
我也尝试在之后调用相机stopPreview
和startPreview
方法,MediaRecorder.start()
但似乎我们不应该这样做,否则当我尝试停止录制(MediaRecorder.stop()
)后,此类操作应用程序将停止响应(它变得冻结)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sample_main);
mPreview = findViewById(R.id.surface_view);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
testVideoRecording();
}
}, 1000);
}
@Override
public void onPreviewFrame(byte[] bytes, Camera camera) {
Log.i(TAG, "onPreviewFrame");
}
private void testVideoRecording() {
mCamera = Camera.open();
Camera.Parameters parameters = mCamera.getParameters();
List<Camera.Size> mSupportedPreviewSizes = parameters.getSupportedPreviewSizes();
List<Camera.Size> mSupportedVideoSizes = parameters.getSupportedVideoSizes();
Camera.Size optimalSize = CameraHelper.getOptimalVideoSize(mSupportedVideoSizes,
mSupportedPreviewSizes, mPreview.getWidth(), mPreview.getHeight());
CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
profile.videoFrameWidth = optimalSize.width;
profile.videoFrameHeight = optimalSize.height;
parameters.setPreviewSize(profile.videoFrameWidth, profile.videoFrameHeight);
mCamera.setParameters(parameters);
try {
mCamera.setPreviewTexture(mPreview.getSurfaceTexture());
} catch (IOException e) {
e.printStackTrace();
}
mCamera.setPreviewCallback(this);
mMediaRecorder = new MediaRecorder();
// Step 1: Unlock and set camera to MediaRecorder
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
// Step 2: Set sources
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
mMediaRecorder.setProfile(profile);
// Step 4: Set output file
mOutputFile = new File(Environment.getExternalStorageDirectory()
+ File.separator + "test.mp4");
if (mOutputFile.exists()) mOutputFile.delete();
mMediaRecorder.setOutputFile(mOutputFile.getPath());
// Step 5: Prepare configured MediaRecorder
try {
mMediaRecorder.prepare();
} catch (IOException e) {
e.printStackTrace();
}
mMediaRecorder.start();
// Step 6: try to set preview frame callback
//mCamera.stopPreview();
try {
mCamera.reconnect();
} catch (IOException e) {
e.printStackTrace();
}
/*try {
mCamera.setPreviewTexture(mPreview.getSurfaceTexture());
} catch (IOException e) {
e.printStackTrace();
}*/
mCamera.setPreviewCallback(this);
//mCamera.startPreview();
}
所以我想知道是否可以同时使用 MediaRecorder 和预览帧回调。如果是,那么如何正确地做到这一点?
解决方案
首先,我强烈建议从已弃用的Camera API ( Camera.open()
, ...) 切换到新的camera2 API,除非您的目标设备都低于 Android API 21。新的 API 更加强大和灵活。例如,它本机支持同一CaptureSession中的多个目标(限制取决于CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL)。这是在同一会话中使用 MediaRecorder 和 ImageReader 的示例。
当 camera2 在设备上处于 LEGACY 级别时,直接使用旧 API 可能仍然更安全(这是此类相机的本地语言)。
如果您坚持使用旧 API,请考虑使用 MediaCodec 和 MediaMuxer 录制视频的示例之一。它比 MediaRecorder 更强大,但需要更多的工作。
显然,问题在于 MediaCodec 出现在 API 21 中,因此这些示例主要与 LEGACY 设备相关。
如果您真的必须使用旧设备,您别无选择,只能运行一些替代视频编码器,从onPreviewFrame()
回调中收到的帧馈送。
推荐阅读
- javascript - 如果单元格等于我的查询,如何从 html 表中获取一行?
- sas - 如何使用宏将名称中带有日期的多个文件读入SAS
- python - DataFrame对象类型列到int或float错误
- android - 如何从特定片段中的活动中禁用 onDestroy 方法?
- javascript - 使用for循环在一个字符串中插入多个字符串
- orientdb - OrientDB 查询适用于 Studio,但不适用于 PyOrient
- javascript - 如何正确等待这个 axios.get 请求?
- c# - 是否有任何简单的方法可以将复杂对象从一个 PageModel 文件传递到 asp.net 核心剃须刀页面(mvvm,而不是 mvc)中的另一个?
- stripe-payments - 在 Laravel Cashier 中处理新的 PaymentIntent 的最佳方法是什么
- flutter - 如何确定缓存的网络图像的宽度和高度?