私はcamera2 apiで週末に遊んでいます。今私は物事がどのように結びついているかを理解し始めるところにいます。 ビデオ録画アプリを実装するためにAPIをテストしている間、私は壁にぶつかった。Androidのcamera2 APIでMediaRecorderのサーフェスを再利用するにはどうすればよいですか?
Android Camera2Video Sampleを私のニーズに変更することから始めました。私の悩みは、各録音プロセスの後にカメラセッションが再現されていることです。さらに悪いことに、レコーディングセッションが開始されると、プレビューセッションが最初に破棄され、レコーディングセッションが作成されます。録音セッションが終了すると、セッションが破棄され、新しいプレビューセッションが作成されます。
ドキュメント明記:セッションの作成
は高価な操作であり、数百ミリ秒を取ることができます... CameraCaptureSession Documentation
を私が打ったときの結果はかなり醜いと画面の吃音記録し、停止する。私はこの振る舞いを改善してコードを手にしたかったのです。私は今何
は、私はすでにそのgetSurface
メソッドを呼び出すことによってMediaRecorder
を作成したから、私のプレビュー表面(TextureView
)を追加しても、表面の私の唯一無二のCameraSession
を作成することです。これは最初のビデオでうまく動作しますが、2番目のビデオをキャプチャしようとするとIllegalArgumentException: Bad argument passed to camera service
となります。これは、MediaRecorder
の表面がCameraSession
に渡されたときに、新しい記録を準備するためにMediaRecorder
をリセットしたときに何らかの形で破壊されたり変更されたりしたためです。
この問題を回避する方法はありますか? (setInputSurface(Surface surface)
)がAPIレベルが高すぎるためテストしなかった可能性があります。
セットアップ
MediaRecorder
private void setUpMediaRecorder() throws IOException { if (mMediaRecorder == null) { mMediaRecorder = new MediaRecorder(); } mMediaRecorder.setVideoEncodingBitRate(5000000); mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mMediaRecorder.setVideoFrameRate(24); mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight()); mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); mMediaRecorder.setOrientationHint(SENSOR_ORIENTATION_DEFAULT_DEGREES); mNextVideoAbsolutePath = getVideoFilePath(); mMediaRecorder.setOutputFile(mNextVideoAbsolutePath); mMediaRecorder.prepare(); }
が記録
SurfaceTexture texture = mTextureView.getSurfaceTexture(); texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); List<Surface> surfaces = new ArrayList<>(); // Set up Surface for the camera preview mPreviewSurface = new Surface(texture); surfaces.add(mPreviewSurface); // Set up Surface for the MediaRecorder mRecorderSurface = mMediaRecorder.getSurface(); surfaces.add(mRecorderSurface); // create the capture session mCameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) { mCameraSession = cameraCaptureSession; // now that the session is created, start using it for the preview showPreview(); } @Override public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) { .... } } }, mBackgroundHandler); } catch (CameraAccessException) { e.printStackTrace(); } void showPreview() { mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); mPreviewBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); mPreviewBuilder.addTarget(mPreviewSurface); mCameraSession.setRepeatingRequest(mPreviewBuilder.build(), null, mBackgroundHandler); }
開始すべての強大なレコーディングセッションを作成します。ここでは
は、関連するコード片の上に簡単な概要です動画mMediaRecorder.stop(); mMediaRecorder.reset(); showPreview(); setUpMediaRecorder(); // this is key to not get an error from the MediaRecorder
を記録
mVideoBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
mVideoBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO);
mVideoBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
mVideoBuilder.addTarget(mPreviewSurface);
mVideoBuilder.addTarget(mRecorderSurface);
// set the request for the capture
mCameraSession.setRepeatingRequest(mVideoBuilder.build(), null, mBackgroundHandler);
// Start recording
mMediaRecorder.start();
ストップはこのすべてが完璧に動作し、録画が開始され、任意のしゃっくりせずに停止します!素晴らしいですが、手順3(4の後)に戻ると、私は前述のIllegalArgumentException: Bad argument passed to camera service
を取得します。私は壁に向かって私の頭を叩いているが、私はこの問題を回避する方法を見つけることができません。
ご協力いただきありがとうございます。
ありがとうございます!