仿微信小視頻錄製控件

效果圖以下:android

    此控件爲組合控件,繼承自 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;// 文件

自定義錄製完成接口:ide

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

錄製視頻時調用下面的方法:post

/**
  * 開始錄製視頻
  * 
  * @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默認的攝像頭爲橫屏,因此要本身設置攝像頭爲豎屏顯示,下面爲初始化攝像頭代碼:this

/**
  * 初始化攝像頭
  * 
  * @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;
  }
 }

初始化攝像頭後,就能夠初始化錄製視頻的工做了,下面爲初始化錄製的代碼:.net

 /**
  * 初始化
  * 
  * @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();
  }
 }

中止拍攝:code

/**
  * 中止拍攝
  * 
  * @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;
 }

自定義控件屬性以下:orm

<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 會報錯,具體緣由還沒找到,因此在錄製的時候必須作一個錄製時間的判斷,若錄製時間過短需作必定的處理。視頻

完整的代碼請看:仿微信小視頻錄製控件繼承

最近在運營一個有關反脆弱成長的我的公衆號,歡迎關注

相關文章
相關標籤/搜索