仿微信小视频

那个第一次写博客,文笔不是太好,所以只好把代码贴出来,然后解释一些,不好意思了,各位
第一方面:下面是对自定义的MovieRecorderView进行的分段解释
第一步:初始化各种数据:布局、参数等
代码:

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public MovieRecorderView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        //下面的参数大多是可以进行配置的:
        // 视频分辨率宽度(分辨率)
        mWidth = 640;
        // 视频分辨率高度(分辨率)
        mHeight = 480;
        // 一次拍摄最长时间
        mRecordMaxTime = 8;
        // 是否一开始就打开摄像头
        isOpenCamera = true;

        LayoutInflater.from(context).inflate(R.layout.view_movie_recorder, this);
        mSurfaceView = (SurfaceView) findViewById(R.id.surfaceview);
        mBottomLayout = (LinearLayout) findViewById(R.id.bottom_layout);
        initSurfaceView(context);
        mProgressBar = (ProgressBar) findViewById(R.id.progressBar);

        mSurfaceHolder = mSurfaceView.getHolder();
        mSurfaceHolder.addCallback(new CustomCallBack());
        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        a.recycle();
    }
 :下面是对应的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/bottom_layout"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        >

        <SurfaceView
            android:id="@+id/surfaceview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            />

    </LinearLayout>
:给SurfaceView添加一个LinearLayout外布局是为了进行第二步的操作;

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="3dp"
        />
</LinearLayout>

第二步:初始化画布:防止在录制视频的时候,屏幕出现拉伸的状况
代码:

private void initSurfaceView(Context context) {
        //获取手机屏幕的宽度
        final int w = DeviceUtils.getScreenWidth(context);
        //可以设置视频的位置:上 下 左 右
        //((LinearLayout.LayoutParams) mBottomLayout.getLayoutParams()).topMargin = w;
        int width = w;
        int height = w * 4 / 3;
    //设置SurfaceView的宽高属性: 这个LayoutParams类是用于child view(子视图) 向 parent view(父视
    //图)传达自己的意愿的一个东西,上面的LinearLayout外布局就是为了设置SurfaceView的宽高
        LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mSurfaceView.getLayoutParams();
        lp.width = width;
        lp.height = height;
        mSurfaceView.setLayoutParams(lp);
    }

第三步:初始化Camera控件,与释放资源
代码:

  /**
     * 初始化摄像头
     * @throws IOException
     */
    private void initCamera() throws IOException {
        if (mCamera != null) {
            //记得一定要释放摄像头资源
            freeCameraResource();
        }

        try {
            mCamera = Camera.open();
            //获取对应手机可以使用的宽高分辨率
  List<Camera.Size> supportedVideoSizes = mCamera.getParameters().getSupportedVideoSizes() == null ? mCamera.getParameters().getSupportedPreviewSizes() : mCamera.getParameters().getSupportedVideoSizes();
   Log.w("TTT", (supportedVideoSizes == null ? "null" : supportedVideoSizes.size()) + "");
   for (Camera.Size supportedVideoSize : supportedVideoSizes) {
   Log.w("TTT", "h:" + supportedVideoSize.height + "--- w:" + supportedVideoSize.width);
            }
        } catch (Exception e) {
            e.printStackTrace();
            freeCameraResource();
        }
        if (mCamera == null)
            return;
       //  setCameraParams();
        //设置摄像头的顺时针方向旋转90度
        mCamera.setDisplayOrientation(90);
        //为摄像头设置SurfaceHolder对象:必须在SurfaceHolder创建完成的时候
        mCamera.setPreviewDisplay(mSurfaceHolder);
        //开启预览功能
        mCamera.startPreview();
        //锁定摄像头
        mCamera.unlock();
    }
 private final Object releaseMutex = new Object();

  /**
     * 释放摄像头资源
     * 添加一个同步锁,防止出现线程的问题
     */
    private void freeCameraResource() {
       synchronized (releaseMutex) {
            if (mCamera != null) {
                mCamera.setPreviewCallback(null);
                mCamera.stopPreview();
                mCamera.lock();
                mCamera.release();
                mCamera = null;
            }
        }
    }

第四步:初始化MediaRecorder控件
代码:

    /**
     * 初始化
     * @throws IOException
     */
    private void initRecord() throws IOException {
        mMediaRecorder = new MediaRecorder();
        mMediaRecorder.reset();
        if (mCamera != null) {
            mMediaRecorder.setCamera(mCamera);
        }
        mMediaRecorder.setOnErrorListener(this);
        mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
        // 视频源
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        // 音频源
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        // 必须在prepare之前,setXXXSource之后
        // 视频输出格式  

        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
      mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);// 音频格式
        mMediaRecorder.setAudioEncodingBitRate(32);
        mMediaRecorder.setAudioSamplingRate(48);
        mMediaRecorder.setVideoSize(mWidth, mHeight);// 设置分辨率:
        //设置视频的帧率
        mMediaRecorder.setVideoFrameRate(24);
        mMediaRecorder.setVideoEncodingBitRate(mBitRate);// 设置帧频率,然后就清晰了
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);// 视频录制格式
       mMediaRecorder.setOrientationHint(90);// 输出旋转90度,保持竖屏录制
        // mediaRecorder.setMaxDuration(Constant.MAXVEDIOTIME * 1000);
        mMediaRecorder.setOutputFile(mRecordFile.getAbsolutePath());
        mMediaRecorder.prepare();
        try {
            mMediaRecorder.start();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (RuntimeException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

第五步:进行录制
代码

/**
     * 开始录制
     * @param mRecordMaxTime : 时间
     * @param mWidth:宽
     * @param mHeight:高
     * @param bitRate:比特率
     * @param onRecordFinishListener:录制完成时的监听
     */
    public void record(final int mRecordMaxTime,int mWidth,int mHeight,int bitRate, final OnRecordFinishListener onRecordFinishListener) {
        //设置一些上面说的可以进行设置的参数
        this.mRecordMaxTime = mRecordMaxTime;
        this.mOnRecordFinishListener = onRecordFinishListener;
        this.mHeight = mHeight;
        this.mWidth = mWidth;
        this.mBitRate = bitRate;
        mProgressBar.setMax(mRecordMaxTime);// 设置进度条最大量
        createRecordDir();
        try {
            if (!isOpenCamera) {// 如果未打开摄像头,则打开
                initCamera();
            }
            initRecord();
            mTimeCount = 0;// 时间计数器重新赋值
            mTimer = new Timer();
            //进行时间计数:刷新ProgressBar条
            mTimer.schedule(new TimerTask() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    mTimeCount++;
                    mProgressBar.setProgress(mTimeCount);// 设置进度条
                    if (mTimeCount == mRecordMaxTime) {// 达到指定时间,停止拍摄
                        stop();
                        if (mOnRecordFinishListener != null)
                            mOnRecordFinishListener.onRecordFinish(getmVecordString(), getmRecordFile(), getTimeCount());
                    }
                }
            }, 0, 1000);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
   /**
     * 录制完成回调接口
     */
    public interface OnRecordFinishListener {
        public void onRecordFinish(String path, File recordFile, int time);
    }

第六步:结束录制与释放资源

     /**
     * 停止拍摄
     */
    public void stop() {
        stopRecord();
        releaseRecord();
        freeCameraResource();
    }**
     * 停止录制
     */
    public void stopRecord() {
        mProgressBar.setProgress(0);
        if (mTimer != null)
            mTimer.cancel();
        if (mMediaRecorder != null) {
            // 设置后不会崩
            mMediaRecorder.setOnErrorListener(null);
            try {
                mMediaRecorder.stop();
            } catch (IllegalStateException e) {
                e.printStackTrace();
            } catch (RuntimeException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
            mMediaRecorder.setPreviewDisplay(null);
        }
    }
    /**
     * 释放资源
     */
    private void releaseRecord() {
        if (mMediaRecorder != null) {
            mMediaRecorder.setOnErrorListener(null);
            try {
                mMediaRecorder.release();
            } catch (IllegalStateException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        mMediaRecorder = null;
    }

第二方面:下面是对录制的主页面进行解释与说明:当初我从网上下的各种相关demo,还有相关的博客说明,在这个地方处理的不多,当我们多次点击手机或者一不小心手抖动了一些之类的,很容易出现bug,所以进行了下面的处理

第一步:录制和停止录制

 //在OnLongClickListener方法中进行录制视频,可以防止多次点击出现的各种bug
        mShootBtn.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                isStart = true;
                //开始录制
                mRecorderView.record(8, 640, 480, MovieRecorderView.BIG_BIT_RATE, new MovieRecorderView.OnRecordFinishListener() {

                    @Override
                    public void onRecordFinish(String path, File recordFile, int time) {
                        isStart = false;
                        handler.sendEmptyMessage(1);
                    }
                });
                //当开始录制后才会走下面的OnTouch事件,走stop
                mShootBtn.setOnTouchListener(new View.OnTouchListener() {
                    @Override
                    public boolean onTouch(View v, MotionEvent event) {
                        if (isStart) {
                            switch (event.getAction()) {
                                case MotionEvent.ACTION_UP:

                                    if (mRecorderView != null) {
                                        mRecorderView.stop();

                                        if (mRecorderView.getTimeCount() > 1) {
                                            finishActivity();
                                        } else {
                                            if (!mRecorderView.getmRecordFile().exists()) {
                                                mRecorderView.getmRecordFile().delete();
                                            }
                                            //   mRecorderView.stop();
                                            Toast.makeText(MainActivity.this,
                                                    getString(R.string.smallTime), Toast.LENGTH_SHORT).show();
                                            MainActivity.this.finish();
                                        }
                                    }
                                    break;

                            }


                        }
                        return true;
                    }
                });
                return true;
            }
        });

第二步:当录制完成之后,生成视频的缩略图,并进行保存和显示

private void finishActivity() {
        if (isFinish) {
            if (mRecorderView != null) {
                //mRecorderView.stop();
                //生成视频的缩略图,并进行保存
                String videoPath = mRecorderView.getmRecordFile().getAbsolutePath();
                Bitmap thumbnailBitmap = Utils.getVoiceBitmap(videoPath, 640, 480);
                String tempBitmapPath = videoPath.substring(0, videoPath.length() - 4);
                String thumbPath = tempBitmapPath + ".jpg";
                saveBitmap(thumbnailBitmap, thumbPath);

                Intent intent = new Intent();
                //视频地址
                intent.putExtra("videoPath", videoPath);
                //缩略图
                intent.putExtra("thumbPath", thumbPath);
                setResult(RESULT_OK, intent);
                finish();
            } else {
                finish();
            }
        }
    }

    /** 保存方法
     * @param getimage
     * @param bitmapPath*/
    public void saveBitmap(Bitmap getimage, String bitmapPath) {
        File f = new File(bitmapPath);
        if (f.exists()) {
            f.delete();
        }
        try {
            FileOutputStream out = new FileOutputStream(f);
            getimage.compress(Bitmap.CompressFormat.PNG, 90, out);
            out.flush();
            out.close();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

代码下载:下载

转载:地址

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值