视频录制和onPreviewFrame同时回调

时间:2018-09-13 13:31:53

标签: android android-camera mediarecorder android-mediarecorder android-video-record

我正在尝试使用MediaRecorder录制视频,并从onPreviewFrame回调方法中获取原始帧(字节数组)

似乎并不是那么容易,mb甚至不可能,我也不知道...

但是我发现了一些答案(针对类似问题),有人说您应该在致电Camera.reconnect()后重新连接相机实例(MediaRecorder.start()),然后再次设置预览回调

我尝试了类似的操作,但是它不起作用(录音有效,但是从未调用onPreviewFrame

我还试图在stopPreview之后调用Camera的startPreviewMediaRecorder.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和预览帧回调。如果是,那该怎么做呢?

2 个答案:

答案 0 :(得分:1)

首先,除非您的目标设备都在Android以下,否则我强烈建议从已弃用的 Camera API(Camera.open(),…)切换到新的camera2 API。 API 21.新的API更加强大和灵活。例如,它本身就在同一 CaptureSession 中支持多个目标(limitations取决于 CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL )。 Here是在同一会话中使用MediaRecorder和ImageReader的示例。

当camera2在设备上处于LEGACY级别时,直接使用旧的API(这是此类摄像机的本机语言)可能仍然更安全。

如果您仍然使用旧的API,请考虑使用MediaCodec和MediaMuxer录制视频的samples之一。它比MediaRecorder强大,但需要更多工作。

很明显,要发现的是MediaCodec出现在API 21中,因此these examples与LEGACY设备最相关。

如果您确实必须使用旧设备,则别无选择,只能运行其他视频编码器,这些编码器由onPreviewFrame()回调中出现的帧提供。

答案 1 :(得分:0)

(根据以下Alex的评论进行编辑)

是的,通常是可能的。相机API可能比较棘手,需要精度和持久性。

首先,从您知道有效的示例代码开始。例如,有关使用原始API捕获视频的官方教程是:https://developer.android.com/guide/topics/media/camera#capture-video。太好了,既然您可以在设备上运行示例代码,那么就已经完成了大部分工作。如果您无法在设备上使用它,请尝试至少使用其他一种品牌的设备。

接下来,让您自己的应用代码与示例的线程和API调用匹配。当您遇到错误或死机时,请查看日志以了解发生了什么。通常这很简单,例如缺少清单中的权限。

最后是日志,日志,日志。在此问题中,如果您已将日志中的错误与代码一起发布,则可能发现了具有特定答案的特定问题。

祝你好运!