仿微信小视频录制控件
仿微信小视频录制控件
人生如歌 发表于3年前
仿微信小视频录制控件
  • 发表于 3年前
  • 阅读 532
  • 收藏 3
  • 点赞 0
  • 评论 1
摘要: 本文为用 MediaRecorder 录制小视频的控件,可以设置视频录制的时间、空间大小、初始时是否打开摄像头等。

效果图如下:

    此控件为组合控件,继承自 LinearLayout ,为防止出错,需实现 android.media.MediaRecorder.OnErrorListener 接口,下面为主要变量:

 private SurfaceView mSurfaceView;
 private SurfaceHolder mSurfaceHolder;
 private ProgressBar mProgressBar;
 private MediaRecorder mMediaRecorder;
 private Camera mCamera;
 private Timer mTimer;// 计时器
 private OnRecordFinishListener mOnRecordFinishListener;// 录制完成回调接口
 private int mWidth;// 视频分辨率宽度
 private int mHeight;// 视频分辨率高度
 private boolean isOpenCamera;// 是否一开始就打开摄像头
 private int mRecordMaxTime;// 一次拍摄最长时间
 private int mTimeCount;// 时间计数
 private File vecordFile = null;// 文件

自定义录制完成接口:

/**
  * 录制完成回调接口
  *
  * @author liuyinjun
  * 
  * @date 2015-2-5
  */
 public interface OnRecordFinishListener {
  public void onRecordFinish();
 }

录制视频时调用下面的方法:

/**
  * 开始录制视频
  * 
  * @author liuyinjun
  * @date 2015-2-5
  * @param fileName
  *            视频储存位置
  * @param onRecordFinishListener
  *            达到指定时间之后回调接口
  */
 public void record(final OnRecordFinishListener onRecordFinishListener) {
  this.mOnRecordFinishListener = onRecordFinishListener;
  createRecordDir();
  try {
   if (!isOpenCamera)// 如果未打开摄像头,则打开
    initCamera();
   initRecord();
   mTimeCount = 0;// 时间计数器重新赋值
   mTimer = new Timer();
   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();
     }
    }
   }, 0, 1000);
  } catch (IOException e) {
   e.printStackTrace();
  }
 } 
 
 
 /**
  * 创建录制文件存储路径
  * @author liuyinjun
  * @date 2015-2-5
  */
 private void createRecordDir() {
  File sampleDir = new File(Environment.getExternalStorageDirectory() + File.separator + "im/video/");
  if (!sampleDir.exists()) {
   sampleDir.mkdirs();
  }
  File vecordDir = sampleDir;
  // 创建文件
  try {
   vecordFile = File.createTempFile("recording", ".mp4", vecordDir);//mp4格式
   LogUtils.i(vecordFile.getAbsolutePath());
  } catch (IOException e) {
  }
 }

由于android默认的摄像头为横屏,所以要自己设置摄像头为竖屏显示,下面为初始化摄像头代码:

/**
  * 初始化摄像头
  * 
  * @author liuyinjun
  * @date 2015-2-5
  * @throws IOException
  */
 private void initCamera() throws IOException {
  if (mCamera != null) {
   freeCameraResource();
  }
  try {
   mCamera = Camera.open();
  } catch (Exception e) {
   e.printStackTrace();
   freeCameraResource();
  }
  if (mCamera == null)
   return;
  setCameraParams();
  mCamera.setDisplayOrientation(90);
  mCamera.setPreviewDisplay(mSurfaceHolder);
  mCamera.startPreview();
  mCamera.unlock();
 } 
 
 /**
  * 设置摄像头为竖屏
  * 
  * @author liuyinjun
  * @date 2015-2-5
  */
 private void setCameraParams() {
  if (mCamera != null) {
   Parameters params = mCamera.getParameters();
   params.set("orientation", "portrait");
   mCamera.setParameters(params);
  }
 }
/**
  * 释放摄像头资源
  * 
  * @author liuyinjun
  * @date 2015-2-5
  */
 private void freeCameraResource() {
  if (mCamera != null) {
   mCamera.setPreviewCallback(null);
   mCamera.stopPreview();
   mCamera.lock();
   mCamera.release();
   mCamera = null;
  }
 }

初始化摄像头后,就可以初始化录制视频的工作了,下面为初始化录制的代码:

 /**
  * 初始化
  * 
  * @author liuyinjun
  * @date 2015-2-5
  * @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(VideoSource.CAMERA);// 视频源
  mMediaRecorder.setAudioSource(AudioSource.MIC);// 音频源
  mMediaRecorder.setOutputFormat(OutputFormat.MPEG_4);// 视频输出格式
  mMediaRecorder.setAudioEncoder(AudioEncoder.AMR_NB);// 音频格式
  mMediaRecorder.setVideoSize(mWidth, mHeight);// 设置分辨率:
  // mMediaRecorder.setVideoFrameRate(16);// 这个我把它去掉了,感觉没什么用
  mMediaRecorder.setVideoEncodingBitRate(1 * 1024 * 512);// 设置帧频率,然后就清晰了
  mMediaRecorder.setOrientationHint(90);// 输出旋转90度,保持竖屏录制
  mMediaRecorder.setVideoEncoder(VideoEncoder.MPEG_4_SP);// 视频录制格式
  // mediaRecorder.setMaxDuration(Constant.MAXVEDIOTIME * 1000);
  mMediaRecorder.setOutputFile(vecordFile.getAbsolutePath());
  mMediaRecorder.prepare();
  try {
   mMediaRecorder.start();
  } catch (IllegalStateException e) {
   e.printStackTrace();
  } catch (RuntimeException e) {
   e.printStackTrace();
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

停止拍摄:

/**
  * 停止拍摄
  * 
  * @author liuyinjun
  * @date 2015-2-5
  */
 public void stop() {
  stopRecord();
  releaseRecord();
  freeCameraResource();
 } 
 
 /**
  * 停止录制
  * 
  * @author liuyinjun
  * @date 2015-2-5
  */
 public void stopRecord() {
  mProgressBar.setProgress(0);
  mProgressBar.postDelayed(new Runnable() {
   @Override
   public void run() {
     mProgressBar.requestLayout();//刷新控件
     }
  }, 100); 
  if (mTimer != null)
   mTimer.cancel();
  if (mMediaRecorder != null) {
   // 设置后不会崩
   mMediaRecorder.setOnErrorListener(null);
   mMediaRecorder.setPreviewDisplay(null);
   try {
    mMediaRecorder.stop();
   } catch (IllegalStateException e) {
    e.printStackTrace();
   } catch (RuntimeException e) {
    e.printStackTrace();
   } catch (Exception e) {
    e.printStackTrace();
   }
  }
 }
 
 
 /**
  * 释放资源
  * 
  */
 private void releaseRecord() {
  if (mMediaRecorder != null) {
   mMediaRecorder.setOnErrorListener(null);
   try {
    mMediaRecorder.release();
   } catch (IllegalStateException e) {
    e.printStackTrace();
   } catch (Exception e) {
    e.printStackTrace();
   }
  }
  mMediaRecorder = null;
 }

自定义控件属性如下:

<declare-styleable name="MovieRecorderView">
        <!-- 开始是否打开摄像头 -->
        <attr name="is_open_camera" format="boolean" />
        <!-- 一次拍摄最长时间 -->
        <attr name="record_max_time" format="integer"/>
        <!-- 视频分辨率宽度 -->
        <attr name="width" format="integer"/>
        <!-- 视频分辨率高度 -->
        <attr name="height" format="integer"/>
    </declare-styleable>

至此关键代码已贴出,只需调用 MovieRecorderView 控件便可实现最长10秒录制的功能。另外,要注意视频录制时间少于1s左右MediaRecorder 会报错,具体原因还没找到,所以在录制的时候必须做一个录制时间的判断,若录制时间太短需做一定的处理。

完整的代码请看:仿微信小视频录制控件

最近在运营一个有关反脆弱成长的个人公众号,欢迎关注

共有 人打赏支持
粉丝 8
博文 15
码字总数 7993
评论 (1)
StruggleLin
可以分享一份源码吗??看了很久,18290287575@163.com
×
人生如歌
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: