视频录制-MediaRecorder

来源:互联网 发布:四维星瓷砖铺贴软件 编辑:程序博客网 时间:2024/05/17 07:26

视频录制:

首先视频的录制和音频的录制都是耗时的,需要在单个线程中去操作,在开启录制时,视频这块的录制,配置参数的前后,有严格的要求,颠倒会报错,报关于Camera,和MediaRecorder的错误,直接上代码,代码里写的很清楚了,对了这块用到了SurfaceView这个控件,不清楚的可以去查查资料。

SurfaceView的初始化工作:

    private void initSurfaceView() {        mSurfaceHolder = mSurfaceView.getHolder();        //设置屏幕分辨率        mSurfaceHolder.setFixedSize(videoWidth, videoHeight);        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);        mSurfaceHolder.addCallback(this);        /**         * 单独处理mSurfaceView的双击事件         */        mSurfaceView.setOnTouchListener(new View.OnTouchListener() {            @Override            public boolean onTouch(View v, MotionEvent event) {                mDetector.onTouchEvent(event);                return true;            }        });    }

实现SurfaceHolder.Callback这个回调,3个方法:

@Override    public void surfaceCreated(SurfaceHolder holder) {        mSurfaceHolder = holder;        startPreView(holder);    }    /**     * 开启预览     *     * @param holder     */    private void startPreView(SurfaceHolder holder) {        if (mCamera == null) {            mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);        }        if (mMediaRecorder == null) {            mMediaRecorder = new MediaRecorder();        }        if (mCamera != null) {            mCamera.setDisplayOrientation(90);            try {                mCamera.setPreviewDisplay(holder);                Camera.Parameters parameters = mCamera.getParameters();                //实现Camera自动对焦                List<String> focusModes = parameters.getSupportedFocusModes();                if (focusModes != null) {                    for (String mode : focusModes) {                        mode.contains("continuous-video");                        parameters.setFocusMode("continuous-video");                    }                }                mCamera.setParameters(parameters);                mCamera.startPreview();            } catch (IOException e) {                e.printStackTrace();            }        }    }    @Override    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {    }    @Override    public void surfaceDestroyed(SurfaceHolder holder) {        if (mCamera != null) {            //停止预览并释放摄像头资源            mCamera.stopPreview();            mCamera.release();            mCamera = null;        }        if (mMediaRecorder != null) {            mMediaRecorder.release();            mMediaRecorder = null;        }    }

onTouch实现按下录制,松开保存功能,上移取消录制:

 @Override    public boolean onTouch(View v, MotionEvent event) {        boolean ret = false;        int action = event.getAction();        float ey = event.getY();        float ex = event.getX();        //只监听中间的按钮处        int vW = v.getWidth();        int left = LISTENER_START;        int right = vW - LISTENER_START;        float downY = 0;        switch (v.getId()) {            case R.id.main_press_control: {                switch (action) {                    case MotionEvent.ACTION_DOWN:                        if (ex > left && ex < right) {                            mProgressBar.setCancel(false);                            //显示上滑取消                            mTvTip.setVisibility(View.VISIBLE);                            mTvTip.setText("↑ 上滑取消");                            //记录按下的Y坐标                            downY = ey;                            // TODO: 2016/10/20 开始录制视频, 进度条开始走                            mProgressBar.setVisibility(View.VISIBLE);                            //开始录制                            Toast.makeText(this, "开始录制", Toast.LENGTH_SHORT).show();                            mRecorderService.submit(new Runnable() {                                @Override                                public void run() {                                    startRecord();                                }                            });                            //更新进度条                            updateProgress();                            ret = true;                        }                        break;                    case MotionEvent.ACTION_UP:                        if (ex > left && ex < right) {                            mTvTip.setVisibility(View.INVISIBLE);                            mProgressBar.setVisibility(View.INVISIBLE);                            stopRecord();                            ret = false;                        }                        break;                    case MotionEvent.ACTION_MOVE:                        if (ex > left && ex < right) {                            float currentY = event.getY();                            if (downY - currentY > 10) {                                isCancel = true;                                mProgressBar.setCancel(true);                            }                        }                        break;                }                break;            }        }        return ret;    }

开启录制和Recorder的配置:
配置顺序很重要,顺序不对,有的手机可以,有的手机会报错

  /**     * 开始录制     */    private void startRecord() {        if (mMediaRecorder != null) {            //没有外置存储, 直接停止录制            if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {                return;            }            try {                if (mMediaRecorder == null) {                    mMediaRecorder = new MediaRecorder();                    /// mMediaRecorder.setOnErrorListener(this);                } else {                    mMediaRecorder.reset();                }                // Step 1: Unlock and set camera to MediaRecorder                mCamera.unlock();                mMediaRecorder.setCamera(mCamera);                mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());                // Step 2: Set sources                mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);//before setOutputFormat()                mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//before setOutputFormat()                //设置视频输出的格式和编码                mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);                CamcorderProfile mProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_CIF);                //after setVideoSource(),after setOutFormat()                //mMediaRecorder.setVideoSize(mProfile.videoFrameWidth, mProfile.videoFrameHeight);                mMediaRecorder.setVideoSize(videoWidth, videoHeight);                mMediaRecorder.setAudioEncodingBitRate(44100);                if (mProfile.videoBitRate > 2 * 1024 * 1024)                    mMediaRecorder.setVideoEncodingBitRate(2 * 1024 * 1024);                else                    mMediaRecorder.setVideoEncodingBitRate(mProfile.videoBitRate);                //after setVideoSource(),after setOutFormat();                mMediaRecorder.setVideoFrameRate(mProfile.videoFrameRate);                //after setOutputFormat()                mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);                //after setOutputFormat()                mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);                // Step 3: Set output file 新建文件保存录制视频                recordFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath()                        + "/RecordDemo/" + System.currentTimeMillis() + ".mp4");                if (!recordFile.getParentFile().exists()) recordFile.getParentFile().mkdirs();                recordFile.createNewFile();                //设置输出路径                mMediaRecorder.setOutputFile(recordFile.getAbsolutePath());                //解决录制视频, 播放器横向问题                mMediaRecorder.setOrientationHint(90);                // Step 4: start and return                mMediaRecorder.prepare();                mMediaRecorder.start();                //     mMediaObject.setStartTime(System.currentTimeMillis());                isRecording = true;            } catch (Exception e) {                e.printStackTrace();            }        }    }

实现进度条的更新操作:

    /**     * 跟新进度条,启用一个线程     */    private void updateProgress() {        mUpdateProgressService.submit(new Runnable() {            @Override            public void run() {                try {                    mProgress = 0;                    isRunning = true;                    while (isRunning) {                        mProgress++;                        Thread.sleep(20);                        //主线程更新进度条                        mHandler.post(new Runnable() {                            @Override                            public void run() {                                mProgressBar.setProgress(mProgress);                            }                        });                    }                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        });    }

松开结束录制:

 private void stopRecord() {        //判断是否为录制结束, 或者为成功录制(时间过短)        if (!isCancel) {            if (mProgress < 50) {                //时间太短不保存                stopRecordUnSave();                Toast.makeText(this, "时间太短", Toast.LENGTH_SHORT).show();            } else {                //停止录制                stopRecordSave();            }        } else {            //现在是取消状态,不保存            stopRecordUnSave();            isCancel = false;            Toast.makeText(this, "取消录制", Toast.LENGTH_SHORT).show();            mProgressBar.setCancel(false);        }    }

保存视频和不保存视频:

/**     * 停止录制 并且保存     */    private void stopRecordSave() {        if (isRecording) {            isRunning = false;            mMediaRecorder.stop();            isRecording = false;            Toast.makeText(MainActivity.this, "视频已经放至" + recordFile.getAbsolutePath(), Toast.LENGTH_SHORT).show();        }    }    /**     * 停止录制, 不保存     */    private void stopRecordUnSave() {        if (isRecording) {            isRunning = false;            mMediaRecorder.stop();            isRecording = false;            if (recordFile.exists()) {                //不保存直接删掉                recordFile.delete();            }        }    }

释放资源:

    private void releaseRecorder() {        if (mMediaRecorder != null) {            mMediaRecorder.release();            mMediaRecorder.reset();            ;            mMediaRecorder = null;        }        if (mCamera != null) {            mCamera.release();            mCamera = null;        }    }

手势的监听,双击实现焦距变化,放大:

    class ZoomGestureListener extends GestureDetector.SimpleOnGestureListener {        //双击手势事件        @Override        public boolean onDoubleTap(MotionEvent e) {            super.onDoubleTap(e);            if (mMediaRecorder != null) {                if (!isZoomIn) {                    setZoom(20);                    isZoomIn = true;                } else {                    setZoom(0);                    isZoomIn = false;                }            }            return true;        }    }

题外:还有一点点代码,和布局这里就不放上了,代码会上传,可以下载看看,试了几个手机,都没有出现问题,这里没有对录制的视频进行压缩,后面会试试看,就先写到这里了,有问题下面提出来就可以了 。

问题:下面这个参考代码有点问题,在小米手机上开启视频录制那里会报错,走catch这块报异常,录制的会发现是0kb,可以把我的这块startRecord这里代码复制过去,覆盖掉那一部分就可以解决了,我这块代码更简洁点,逻辑更清楚点,也可以下我的代码,效果会好一点……

参考:http://www.jianshu.com/p/6f84739ab85f

demo下载:https://github.com/amelons/RecordVideoSample

转载标明:http://blog.csdn.net/zxyudia/article/details/69265263

0 0
原创粉丝点击