Android自定义相机(三) —— 录像

前面我们已经大致完成了自定义相机的拍照功能,接下来,我们来实现一下录像的功能。

1、录像功能简介

录像功能的是相对比较简单,因为步骤是很固定的,google给我们提供的api文档中说的也比较详细,这里我们主要用到 MediaRecorder 这个类。

MediaRecorder的状态图

Android自定义相机(三) —— 录像_第1张图片

同时还给我们提供了示例用法

Android自定义相机(三) —— 录像_第2张图片

2、代码实现

接下来我们就照着api中的示例做就可以了

(一)开始录像

private MediaRecorder mMediaRecorder;
    private boolean isRecord = false;
    //开始录像
    public void startRecord(){
        mCamera.unlock();
        isRecord = true;
        mMediaRecorder = new MediaRecorder();
        mMediaRecorder.reset();
        mMediaRecorder.setCamera(mCamera);
        //录制的视频的角度,要自行旋转,否则与预览角度不同 
        mMediaRecorder.setOrientationHint(90);
        if(cameraId == CameraInfo.CAMERA_FACING_FRONT){
            mMediaRecorder.setOrientationHint(270);
        }
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        // 设置录像的质量(分辨率,帧数)
        /**
        * 下面两行代码的设置也可以具体写:
        * mMediaRecorder.setVideoSize(320, 240);//分辨率
        * mMediaRecorder.setVideoFrameRate(5);//帧数
        * 用别人的demo是没有问题的,但是我自己写的过程中总是出蜜汁BUG,
        * 而且各种方法都试了也无法解决,只能放弃了
        */
        CamcorderProfile mCamcorderProfile = CamcorderProfile.get(cameraId,
                CamcorderProfile.QUALITY_720P);
        mMediaRecorder.setProfile(mCamcorderProfile);
        // 设置视频文件输出的路径  
        mMediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString());
        // 设置捕获视频图像的预览界面  
        mMediaRecorder.setPreviewDisplay(holder.getSurface());

        try {
            mMediaRecorder.prepare();
        } catch (Exception e) {
            isRecord = false;
            e.printStackTrace();
            mCamera.lock();
        }
        mMediaRecorder.start();
    }

    //------------------------ 分割线 --------------------------

    private static final int MEDIA_TYPE_IMAGE = 1;//图片类型
    private static final int MEDIA_TYPE_VIDEO = 2;//视频类型

    //获取文件保存的位置,目录不存在就创建
    private File getOutputMediaFile(int type) {
        File mediaFile = null;
        if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
            String filePath = "/sdcard/WaterCamera";
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
            if (type == MEDIA_TYPE_IMAGE){
                mediaFile = new File(filePath + File.separator +
                        "IMG_"+ timeStamp + ".jpg");
            } else if(type == MEDIA_TYPE_VIDEO) {
                mediaFile = new File(filePath + File.separator +
                        "VID_"+ timeStamp + ".mp4");
            }
            if(!mediaFile.exists()){
                if(!mediaFile.getParentFile().exists()){
                    mediaFile.getParentFile().mkdirs();
                }
                try {
                    mediaFile.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return mediaFile;
    }

(二)结束录像

//停止录像
public void stopRecord(){
    if(mMediaRecorder !=null){
           if(isRecord){
               mMediaRecorder.stop();
               mMediaRecorder.reset();
               mMediaRecorder.release();
               mMediaRecorder =null;
               isRecord = false;
           }
       }
    //重新设置预览,否则会出现连续拍照崩溃的问题
    mCamera.stopPreview();//停掉原来摄像头的预览
       mCamera.release();//释放资源
       mCamera = null;
    //重新预览
    mCamera = Camera.open(cameraId);
    setCameraParams(this.getWidth(),this.getHeight());
    try {
        mCamera.setPreviewDisplay(holder);
    } catch (IOException e) {
        e.printStackTrace();
    }
    mCamera.startPreview();
}

3、遇到的问题

虽然步骤很简单,但是也有一些坑,最常见的就是 start failed: -19 这个错误了:

Android自定义相机(三) —— 录像_第3张图片

这个问题真是困扰了我一段时间,肯定是start之前设置有问题,主要问题还是出在这两行代码:

mMediaRecorder.setVideoSize(320, 240);//分辨率
mMediaRecorder.setVideoFrameRate(5);//帧数

用这种方式写,无论是想根据摄像头支持的分辨率列表里面找合适的尺寸我这里都会出现bug,网上也有说注释掉这两句,或者添加camera.lock()和camera.unlock()之类的都不管用,不过在别人的demo里面这么写是完全正常的,后来还是看别人的写法,采用这种写法,才没报错:

CamcorderProfile mCamcorderProfile = CamcorderProfile.get(cameraId,
CamcorderProfile.QUALITY_720P);
mMediaRecorder.setProfile(mCamcorderProfile);

在上面代码的参数CamcorderProfile.QUALITY_720P是可以自己调节的,一半是CamcorderProfile.QUALITY_HIGH,但是我设置成这个参数会导致预览界面图像被压缩,所以就找了个看着比较正常的填了进去。

小结

录像功能基本算是完成了,虽然很粗糙,下面贴一下我的自定义的surfaceview吧,用法比较简单,在layout中引用,Activity中用 CameraSurfaceView.getInstance() 获取对象然后点出方法就可以。
链接:
CameraSurfaceView.java
MatrixUtils.java

你可能感兴趣的:(自定义相机)