视频录制-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
- MediaRecorder录制视频
- 视频录制MediaRecorder
- MediaRecorder录制视频
- MediaRecorder录制视频
- 录制视频之MediaRecorder
- Android MediaRecorder视频录制
- MediaRecorder 录制视频
- 录制视频(Surfaceview+MediaRecorder)
- 视频录制-MediaRecorder
- MediaRecorder录制视频
- MediaRecorder之视频录制
- Android MediaRecorder录制视频
- 使用MediaRecorder录制音视频
- 使用MediaRecorder进行视频录制
- Android MediaRecorder 后台视频录制
- Android MediaRecorder视频录制,多分辨率调节
- android MediaRecorder 录制音频、视频代码片段
- Android MediaRecorder视频录制,多分辨率调节
- JS兼容各个浏览器的本地图片上传即时预览效果
- Spring MVC配置MyBatis输出SQL
- 数据库的主键和外键
- JS如何实现点击页面其他地方隐藏菜单?
- 单例 Dialog 自定义
- 视频录制-MediaRecorder
- 解决Android7.0系统 调用系统相机、系统播放器播放视频、切图兼容问题,报异常android.os.FileUriExposedException
- 收缩表空间大小
- Zookeeper概述
- eclipse集成jboss,deployment无法修改项目部署路径
- Laravel 校验规则之字段值唯一性校验
- 四塔问题 ssl 2632 规律题
- 大数据看两会热词:脱贫/扶贫
- tensorflow 学习(1) minist数据初入