文档章节

仿微信小视频录制控件

人生如歌
 人生如歌
发布于 2015/03/01 22:35
字数 984
阅读 584
收藏 3

效果图如下:

    此控件为组合控件,继承自 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 会报错,具体原因还没找到,所以在录制的时候必须做一个录制时间的判断,若录制时间太短需做一定的处理。

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

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

© 著作权归作者所有

共有 人打赏支持
人生如歌
粉丝 7
博文 15
码字总数 7993
作品 0
深圳
程序员
加载中

评论(1)

S
StruggleLin
可以分享一份源码吗??看了很久,18290287575@163.com
Android 视频录制控件--LQRViedoRecordView

安卓视频录制控件,可以用来仿微信小视频。 一、使用 1、引入依赖 compile 'com.lqr.videorecordview:library:1.0.0' 2、布局中引用 <com.lqr.videorecordview.LQRVideoRecordView android:...

CSDN_LQR
2017/01/13
1K
0
仿微信小视频录制控件里的小问题

@人生如歌 你好,想跟你请教个问题: 仿微信小视频录制控件 MainActivity 里的第91行VideoPlayerActivity是单独的一个类吗,没有找到,我在电脑里这里出错了,希望你能帮忙回答一下,谢谢!...

liuluyeah
2016/03/04
104
0
Android UI框架(中)

唯美清新的switch按钮 优雅的switch状态按钮 通用的引导页和轮播器 仿微信图片选择器 快捷设置沉浸式状态栏 复杂表格布局 最全的开源集合 阻尼效果的界面 炫酷的纸飞机下拉刷新控件 仿ios水滴...

Moosphon
2017/12/31
0
0
CSDN_LQR/LQRWeChat

重大消息!!! 新版高仿微信已经开源,因为基于融云SDK,使用了 Rxjava+Retrofit+MVP+Glide 等新技术开发,代码结构上可以完全不一样,所以另开了一个项目。新版高仿微信使用到了自动布局来...

CSDN_LQR
2017/02/07
0
0
Swift 3.0 高仿微信--LXFWeChat

Swift 3.0 高仿微信 模仿微信的导航栏 在navigationBar底部添加一个添加了渐变层的view let blurBackView = UIView()blurBackView.frame = CGRect(x: 0, y: -20, width: kScreenW, height: ......

LinXunFeng
2017/02/16
379
0

没有更多内容

加载失败,请刷新页面

加载更多

nginx的简单使用:负载均衡

nginx:反向代理的服务器;用户发送请求到nginx,nginx把请求发送给真正的服务器,等待服务器处理完数据并返回,再把数据发送给用户。 nginx作为一个反向代理服务器,能缓存我们项目的静态文...

osliang
25分钟前
1
0
网站title标题被改并被百度网址安全中心提醒的解决办法

国庆假日期间我们Sine安全接到众多网站站长求助网站标题被改导致在百度搜索中百度安全中心提醒被拦截,导致网站正常用户无法浏览网站被跳转到一些菠菜du博网站,而且很明显的一个特征就是在百...

网站安全
27分钟前
1
0
JDK版本与major.minor version的对照关系

其实,只需要记住jdk6对于major.minor version 50即可,其他版本自行计算即可。 ---------------------

码代码的小司机
29分钟前
1
0
C++基础教程面向对象学习笔记及心得感悟[图]

C++基础教程面向对象学习笔记及心得感悟[图] 使用友元函数重载算术运算符: C ++中一些最常用的运算符是算术运算符 - 即加号运算符(+),减运算符( - ),乘法运算符(*)和除法运算符(/...

原创小博客
38分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部