http://developer.android.com/guide/topics/media/camera.html
Note: It is possible to use MediaRecorder without creating a camera preview first and skip the first few steps of this process. However, since users typically prefer to see a preview before starting a recording, that process is not discussed here.
Android的文档如上,我想不创建一个照相机的预览界面,按理来说是可行的。我参考文档里的步骤,省去startpreview.核心代码如下
public void init(){
CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
Log.e(TAG, "OpenCamera-Video E");
String cameraId = null;
try {
if(!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)){
throw new RuntimeException("Time out waiting to lock Camera opening");
}
cameraId = manager.getCameraIdList()[0];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
mVideoSize = chooseVideoSize(map.getOutputSizes(MediaRecorder.class));
mMediaRecorder = new MediaRecorder();
manager.openCamera(cameraId,mStateCallback,null);
setUpMediaRecorder();
} catch (CameraAccessException e) {
e.printStackTrace();
Log.e(TAG,"cannot access the camera");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Log.e(TAG,"openCamera-video X");
}
private void setUpMediaRecorder() throws IOException {
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setVideoEncodingBitRate(10000000);
mMediaRecorder.setVideoFrameRate(30);
mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight());
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setOutputFile(String.valueOf(getVideoFile()));
//mMediaRecorder.setOrientationHint(orientation);
mMediaRecorder.prepare();
}
private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice cameraDevice) {
mCameraDevice = cameraDevice;
mCameraOpenCloseLock.release();
}
@Override
public void onDisconnected(CameraDevice cameraDevice) {
mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice = null;
}
@Override
public void onError(CameraDevice cameraDevice, int i) {
mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice = null;
}
};
private void startRecordingVideo() {
try {
// UI
// mButtonVideo.setText(R.string.stop);
mIsRecordingVideo = true;
Log.i("VideoService","在startRecordingVideo里");
// Start recording
mMediaRecorder.start();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
private boolean mIsRecordingVideo = false;
private void stopRecordingVideo() {
// UI
mIsRecordingVideo = false;
// mButtonVideo.setText(R.string.record);
// Stop recording
mMediaRecorder.stop();
mMediaRecorder.reset();
mMediaRecorder.release();
// Activity activity = getActivity();
Toast.makeText(this, "Video saved: " + getVideoFile(),
Toast.LENGTH_SHORT).show();
// startPreview();
}
在初始化的时候执行init()函数,之后,点击button按钮,对mIsRecordingVideo值判断,若为false,进入startRecordingVideo(),启动录像;若为true,进入stopRecordingVideo(),停止录像。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
根据您提供的代码和问题描述,您希望在不创建相机预览界面的情况下使用 MediaRecorder
进行视频录制。以下是针对您的需求的详细分析和解决方案。
根据 Android 官方文档的说明,确实可以跳过相机预览步骤直接使用 MediaRecorder
进行录制。然而,这种操作需要确保以下几点: - Surface 配置正确:即使没有预览界面,MediaRecorder
仍然需要一个有效的 Surface
来接收视频帧数据。 - 权限处理:确保应用已动态申请并获得必要的权限(如摄像头、麦克风、存储等)。 - 生命周期管理:正确管理 CameraDevice
和 MediaRecorder
的生命周期,避免资源泄漏或异常崩溃。
在您的 init()
方法中,已经完成了大部分初始化工作,但缺少为 MediaRecorder
提供 Surface
的关键步骤。以下是改进后的代码:
private Surface mRecorderSurface;
public void init() {
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
Log.e(TAG, "OpenCamera-Video E");
String cameraId = null;
try {
if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
throw new RuntimeException("Time out waiting to lock Camera opening");
}
cameraId = manager.getCameraIdList()[0];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
mVideoSize = chooseVideoSize(map.getOutputSizes(MediaRecorder.class));
// 创建 MediaRecorder 并设置 Surface
mMediaRecorder = new MediaRecorder();
setUpMediaRecorder();
// 创建 Surface 用于 MediaRecorder
mRecorderSurface = mMediaRecorder.getSurface();
// 打开相机
manager.openCamera(cameraId, mStateCallback, null);
} catch (CameraAccessException | InterruptedException | IOException e) {
e.printStackTrace();
Log.e(TAG, "Cannot access the camera or set up MediaRecorder");
}
Log.e(TAG, "openCamera-video X");
}
关键点: - 使用 mMediaRecorder.getSurface()
获取 Surface
,并将其传递给相机作为输出目标。 - 确保 setUpMediaRecorder()
方法中配置了正确的输出格式、编码器和文件路径。
在 setUpMediaRecorder()
方法中,您已经完成了大部分配置。以下是完整的代码示例:
private void setUpMediaRecorder() throws IOException {
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setVideoEncodingBitRate(10000000);
mMediaRecorder.setVideoFrameRate(30);
mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight());
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
// 设置输出文件路径
mMediaRecorder.setOutputFile(getVideoFile().getAbsolutePath());
// 准备 MediaRecorder
mMediaRecorder.prepare();
}
注意: - getVideoFile()
方法应返回一个有效的文件路径,例如:
private File getVideoFile() {
return new File(getExternalFilesDir(null), "video.mp4");
}
在 CameraDevice.StateCallback
中,需要将 Surface
绑定到相机会话。以下是改进后的代码:
private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice cameraDevice) {
mCameraDevice = cameraDevice;
mCameraOpenCloseLock.release();
// 创建 CaptureRequest 并绑定 Surface
try {
final CaptureRequest.Builder captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
captureBuilder.addTarget(mRecorderSurface);
// 创建 CameraCaptureSession
mCameraDevice.createCaptureSession(
Arrays.asList(mRecorderSurface),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession session) {
try {
session.setRepeatingRequest(captureBuilder.build(), null, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(CameraCaptureSession session) {
Log.e(TAG, "CameraCaptureSession configuration failed");
}
},
null
);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onDisconnected(CameraDevice cameraDevice) {
mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice = null;
}
@Override
public void onError(CameraDevice cameraDevice, int error) {
mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice = null;
}
};
关键点: - 使用 createCaptureRequest(CameraDevice.TEMPLATE_RECORD)
创建录制请求,并将 mRecorderSurface
添加为目标。 - 调用 createCaptureSession
创建会话,并设置重复请求以持续捕获视频帧。
在 startRecordingVideo()
和 stopRecordingVideo()
方法中,您已经实现了基本逻辑。以下是完整代码:
private void startRecordingVideo() {
try {
mIsRecordingVideo = true;
mMediaRecorder.start();
Log.i("VideoService", "Recording started");
} catch (IllegalStateException e) {
e.printStackTrace();
Log.e(TAG, "Failed to start recording");
}
}
private void stopRecordingVideo() {
mIsRecordingVideo = false;
try {
mMediaRecorder.stop();
mMediaRecorder.reset();
mMediaRecorder.release();
Toast.makeText(this, "Video saved: " + getVideoFile().getAbsolutePath(), Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Failed to stop recording");
}
}
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
onPause()
或 onDestroy()
中释放 CameraDevice
和 MediaRecorder
资源。通过上述改进,您可以实现无需预览界面的视频录制功能,同时确保代码的稳定性和可维护性。您可以复制页面截图提供更多信息,我可以进一步帮您分析问题原因。